From 304f9fd0d37cef5b6676bafe07ae8c0905ffe6cb Mon Sep 17 00:00:00 2001 From: Javier Goizueta Date: Wed, 13 Mar 2019 13:40:02 +0100 Subject: [PATCH 01/20] Merge pull request #551 from CartoDB/tomtom-bulk-fix Fix altered public method of TomTomGeocoder --- NEWS.md | 5 +++++ .../cartodb_services/cartodb_services/tomtom/geocoder.py | 8 ++++++-- server/lib/python/cartodb_services/setup.py | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 5470a5b..d6a4455 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,8 @@ +Mar 13rd, 2019 +============== +* Version `0.21.4` of the python library + * Fix TomTom bulk geocoder bug (#551) + Mar 5th, 2019 ============== * Version `0.21.3` of the python library diff --git a/server/lib/python/cartodb_services/cartodb_services/tomtom/geocoder.py b/server/lib/python/cartodb_services/cartodb_services/tomtom/geocoder.py index 5e1ac5b..81148ec 100644 --- a/server/lib/python/cartodb_services/cartodb_services/tomtom/geocoder.py +++ b/server/lib/python/cartodb_services/cartodb_services/tomtom/geocoder.py @@ -73,16 +73,20 @@ class TomTomGeocoder(Traceable): @qps_retry(qps=5, provider='tomtom') def geocode(self, searchtext, city=None, state_province=None, country=None): - geocoder_response, http_response = self.geocode_meta(searchtext, city, state_province, country) + geocoder_response, http_response = self._geocode_meta(searchtext, city, state_province, country) error_message = geocoder_response[1].get('error', None) if error_message: raise ServiceException(error_message, http_response) else: return geocoder_response[0] - @qps_retry(qps=5, provider='tomtom') def geocode_meta(self, searchtext, city=None, state_province=None, country=None): + return self._geocode_meta(searchtext, city, state_province, country)[0] + + @qps_retry(qps=5, provider='tomtom') + def _geocode_meta(self, searchtext, city=None, state_province=None, + country=None): if searchtext: searchtext = searchtext.decode('utf-8') if city: diff --git a/server/lib/python/cartodb_services/setup.py b/server/lib/python/cartodb_services/setup.py index d4f2a25..4a272ce 100644 --- a/server/lib/python/cartodb_services/setup.py +++ b/server/lib/python/cartodb_services/setup.py @@ -10,7 +10,7 @@ from setuptools import setup, find_packages setup( name='cartodb_services', - version='0.21.3', + version='0.21.4', description='CartoDB Services API Python Library', From 8b0ec7b6f52214b248d65ec1f22c615d50da1cc8 Mon Sep 17 00:00:00 2001 From: Raul Marin Date: Mon, 7 Oct 2019 18:09:37 +0200 Subject: [PATCH 02/20] Fix CI --- .../python/cartodb_services/test/test_mapboxrouting.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/lib/python/cartodb_services/test/test_mapboxrouting.py b/server/lib/python/cartodb_services/test/test_mapboxrouting.py index 160b2a5..f9a56c2 100644 --- a/server/lib/python/cartodb_services/test/test_mapboxrouting.py +++ b/server/lib/python/cartodb_services/test/test_mapboxrouting.py @@ -27,7 +27,7 @@ WELL_KNOWN_SHAPE = [(40.73312, -73.98891), (40.73353, -73.98987), (40.73219, -73.99856), (40.73222, -73.99861), (40.73225, -73.99868), (40.73293, -74.00007), (40.733, -74.00001)] -WELL_KNOWN_LENGTH = 1317.9 +WELL_KNOWN_LENGTH = 1384.9 class MapboxRoutingTestCase(unittest.TestCase): @@ -59,6 +59,8 @@ class MapboxRoutingTestCase(unittest.TestCase): def test_valid_request(self): route = self.routing.directions(VALID_WAYPOINTS, VALID_PROFILE) - self.assertEqual(route.shape, WELL_KNOWN_SHAPE) - self.assertEqual(route.length, WELL_KNOWN_LENGTH) + assert route.shape # The duration may change with time + # Since the distance varies with the route, accept a margin + self.assertGreater(route.length, WELL_KNOWN_LENGTH * 0.9) + self.assertLess(route.length, WELL_KNOWN_LENGTH * 1.1) assert route.duration # The duration may change between executions From 2a68291da7ec79332daebe16bdd6147a2b19aefd Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Fri, 17 Jan 2020 17:04:43 +0100 Subject: [PATCH 03/20] First implementation of the true Mapbox isochrones --- client/renderer/interface.yaml | 26 ++++ server/extension/sql/80_isolines_helper.sql | 122 +++++++++++++++ server/extension/sql/85_isodistance.sql | 17 +++ server/extension/sql/90_isochrone.sql | 16 ++ .../cartodb_services/mapbox/__init__.py | 1 + .../cartodb_services/mapbox/true_isolines.py | 142 ++++++++++++++++++ .../cartodb_services/mapbox/types.py | 1 + .../cartodb_services/metrics/config.py | 41 +++++ .../cartodb_services/metrics/user.py | 2 + .../service/mapbox_true_isolines_config.py | 123 +++++++++++++++ server/lib/python/cartodb_services/setup.py | 2 +- .../test/metrics/test_config.py | 4 +- .../cartodb_services/test/test_helper.py | 1 + .../test/test_mapboxtrueisoline.py | 33 ++++ .../test/test_quota_service.py | 17 +++ 15 files changed, 546 insertions(+), 2 deletions(-) create mode 100644 server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py create mode 100644 server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py create mode 100644 server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py diff --git a/client/renderer/interface.yaml b/client/renderer/interface.yaml index 7f94d28..7ec2a31 100644 --- a/client/renderer/interface.yaml +++ b/client/renderer/interface.yaml @@ -210,6 +210,19 @@ - { name: range, type: "integer[]" } - { name: options, type: "text[]", default: 'ARRAY[]::text[]' } +- name: cdb_mapbox_iso_isochrone + return_type: SETOF cdb_dataservices_client.isoline + multi_row: true + multi_field: true + requires_permission: true + permission_name: isolines + permission_error: Isolines permission denied + params: + - { name: source, type: "public.geometry(Geometry, 4326)" } + - { name: mode, type: text } + - { name: range, type: "integer[]" } + - { name: options, type: "text[]", default: 'ARRAY[]::text[]' } + - name: cdb_tomtom_isochrone return_type: SETOF cdb_dataservices_client.isoline multi_row: true @@ -249,6 +262,19 @@ - { name: range, type: "integer[]" } - { name: options, type: "text[]", default: 'ARRAY[]::text[]' } +- name: cdb_mapbox_iso_isodistance + return_type: SETOF cdb_dataservices_client.isoline + multi_row: true + multi_field: true + requires_permission: true + permission_name: isolines + permission_error: Isolines permission denied + params: + - { name: source, type: "public.geometry(Geometry, 4326)" } + - { name: mode, type: text } + - { name: range, type: "integer[]" } + - { name: options, type: "text[]", default: 'ARRAY[]::text[]' } + - name: cdb_tomtom_isodistance return_type: SETOF cdb_dataservices_client.isoline multi_row: true diff --git a/server/extension/sql/80_isolines_helper.sql b/server/extension/sql/80_isolines_helper.sql index ade6b65..988855a 100644 --- a/server/extension/sql/80_isolines_helper.sql +++ b/server/extension/sql/80_isolines_helper.sql @@ -188,6 +188,70 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.quota_service.increment_total_service_use() $$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxTrueIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapbox_iso_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox true isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox true isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance( username TEXT, orgname TEXT, @@ -372,6 +436,64 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.quota_service.increment_total_service_use() $$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxTrueIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + resp = mapbox_iso_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox true isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox true isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones( username TEXT, orgname TEXT, diff --git a/server/extension/sql/85_isodistance.sql b/server/extension/sql/85_isodistance.sql index fbe192e..85811ee 100644 --- a/server/extension/sql/85_isodistance.sql +++ b/server/extension/sql/85_isodistance.sql @@ -26,6 +26,9 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ elif user_isolines_config.mapbox_provider: mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_iso_provider: + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) elif user_isolines_config.tomtom_provider: tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) @@ -76,6 +79,20 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ return result $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +-- mapbox true isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + -- tomtom isodistance CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ diff --git a/server/extension/sql/90_isochrone.sql b/server/extension/sql/90_isochrone.sql index 731a27e..035ab0f 100644 --- a/server/extension/sql/90_isochrone.sql +++ b/server/extension/sql/90_isochrone.sql @@ -26,6 +26,9 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ elif user_isolines_config.mapbox_provider: mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_iso_provider: + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) elif user_isolines_config.tomtom_provider: tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) @@ -74,6 +77,19 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ return result $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +-- mapbox true isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + -- tomtom isochrone CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/__init__.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/__init__.py index 10ca46e..5709f66 100644 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/__init__.py +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/__init__.py @@ -2,4 +2,5 @@ from routing import MapboxRouting, MapboxRoutingResponse from geocoder import MapboxGeocoder from bulk_geocoder import MapboxBulkGeocoder from isolines import MapboxIsolines, MapboxIsochronesResponse +from true_isolines import MapboxTrueIsolines, MapboxTrueIsochronesResponse from matrix_client import MapboxMatrixClient diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py new file mode 100644 index 0000000..2fa53c6 --- /dev/null +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py @@ -0,0 +1,142 @@ +import json +import requests +from uritemplate import URITemplate + +from cartodb_services.tools.exceptions import ServiceException +from cartodb_services.tools.qps import qps_retry +from cartodb_services.tools import Coordinate + +BASEURI = ('https://api.mapbox.com/isochrone/v1/mapbox/{profile}/{coordinates}?contours_minutes={contours_minutes}&access_token={apikey}') + +PROFILE_DRIVING = 'driving' +PROFILE_CYCLING = 'cycling' +PROFILE_WALKING = 'walking' +DEFAULT_PROFILE = PROFILE_DRIVING + +MAX_SPEEDS = { + PROFILE_WALKING: 3.3333333, # In m/s, assuming 12km/h walking speed + PROFILE_CYCLING: 16.67, # In m/s, assuming 60km/h max speed + PROFILE_DRIVING: 41.67 # In m/s, assuming 140km/h max speed +} + +VALID_PROFILES = [PROFILE_DRIVING, + PROFILE_CYCLING, + PROFILE_WALKING] + +ENTRY_FEATURES = 'features' +ENTRY_GEOMETRY = 'geometry' + + +class MapboxTrueIsolines(): + ''' + Python wrapper for Mapbox based isolines. + ''' + + def __init__(self, apikey, logger, service_params=None): + service_params = service_params or {} + self._apikey = apikey + self._logger = logger + + def _uri(self, origin, time_range, profile=DEFAULT_PROFILE): + uri = URITemplate(BASEURI).expand(apikey=self._apikey, + coordinates=origin, + contours_minutes=time_range, + profile=profile) + return uri + + def _validate_profile(self, profile): + if profile not in VALID_PROFILES: + raise ValueError('{profile} is not a valid profile. ' + 'Valid profiles are: {valid_profiles}'.format( + profile=profile, + valid_profiles=', '.join( + [x for x in VALID_PROFILES]))) + + def _parse_coordinates(self, boundary): + return [Coordinate(c[0], c[1]) for c in boundary] + + def _parse_isochrone_service(self, response): + json_response = json.loads(response) + + coordinates = [] + if json_response: + for feature in json_response[ENTRY_FEATURES]: + geometry = feature[ENTRY_GEOMETRY] + coordinates.append(self._parse_coordinates(geometry)) + + return coordinates + + @qps_retry(qps=5, provider='mapbox_iso') + def _calculate_isoline(self, origin, time_ranges, + profile=DEFAULT_PROFILE): + origin = '{lon},{lat}'.format(lat=origin.latitude, + lon=origin.longitude) + + time_ranges.sort() + time_ranges_seconds = ','.join([str(round(t/60)) for t in time_ranges]) + + uri = self._uri(origin, time_ranges_seconds, profile) + + try: + response = requests.get(uri) + + if response.status_code == requests.codes.ok: + isolines = [] + + coordinates = self._parse_isochrone_service(response.text) + for t, c in zip(time_ranges, coordinates): + isolines.append(MapboxTrueIsochronesResponse(c, t)) + + return isolines + elif response.status_code == requests.codes.bad_request: + return [] + elif response.status_code == requests.codes.unprocessable_entity: + return [] + else: + raise ServiceException(response.status_code, response) + except requests.Timeout as te: + # In case of timeout we want to stop the job because the server + # could be down + self._logger.error('Timeout connecting to Mapbox isochrone service', + te) + raise ServiceException('Error getting isochrone data from Mapbox', + None) + except requests.ConnectionError as ce: + # Don't raise the exception to continue with the geocoding job + self._logger.error('Error connecting to Mapbox isochrone service', + exception=ce) + return [] + + def calculate_isochrone(self, origin, time_ranges, + profile=DEFAULT_PROFILE): + self._validate_profile(profile) + + return self._calculate_isoline(origin=origin, + time_ranges=time_ranges, + profile=profile) + + def calculate_isodistance(self, origin, distance_range, + profile=DEFAULT_PROFILE): + self._validate_profile(profile) + + max_speed = MAX_SPEEDS[profile] + time_range = distance_range / max_speed + + return self._calculate_isoline(origin=origin, + time_ranges=[time_range], + profile=profile)[0].coordinates + + +class MapboxTrueIsochronesResponse: + + def __init__(self, coordinates, duration): + self._coordinates = coordinates + self._duration = duration + + @property + def coordinates(self): + return self._coordinates + + @property + def duration(self): + return self._duration diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/types.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/types.py index cc55bac..57c6764 100644 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/types.py +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/types.py @@ -1,6 +1,7 @@ MAPBOX_ROUTING_APIKEY_ROUNDROBIN = 'mapbox_routing_apikey_roundrobin' MAPBOX_GEOCODER_APIKEY_ROUNDROBIN = 'mapbox_geocoder_apikey_roundrobin' MAPBOX_ISOLINES_APIKEY_ROUNDROBIN = 'mapbox_isolines_apikey_roundrobin' +MAPBOX_ISO_ISOLINES_APIKEY_ROUNDROBIN = 'mapbox_iso_isolines_apikey_roundrobin' TRANSPORT_MODE_TO_MAPBOX = { 'car': 'driving', diff --git a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py index 3e45694..6134848 100644 --- a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py +++ b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py @@ -224,6 +224,7 @@ class IsolinesRoutingConfig(ServiceConfig): GEOCODER_PROVIDER_KEY = 'geocoder_provider' MAPZEN_PROVIDER = 'mapzen' MAPBOX_PROVIDER = 'mapbox' + MAPBOX_ISO_PROVIDER = 'mapbox' TOMTOM_PROVIDER = 'tomtom' HEREMAPS_PROVIDER = 'heremaps' DEFAULT_PROVIDER = MAPBOX_PROVIDER @@ -258,6 +259,9 @@ class IsolinesRoutingConfig(ServiceConfig): self._mapbox_matrix_api_keys = self._db_config.mapbox_matrix_api_keys self._mapbox_matrix_service_params = db_config.mapbox_matrix_service_params self._mapbox_isochrones_service_params = db_config.mapbox_isochrones_service_params + elif self._isolines_provider == self.MAPBOX_ISO_PROVIDER: + self._mapbox_iso_isolines_api_keys = self._db_config.mapbox_iso_isolines_api_keys + self._mapbox_iso_isolines_service_params = db_config.mapbox_iso_isolines_service_params elif self._isolines_provider == self.TOMTOM_PROVIDER: self._tomtom_isolinesx_api_keys = self._db_config.tomtom_isolines_api_keys self._tomtom_isolines_service_params = db_config.tomtom_isolines_service_params @@ -270,6 +274,8 @@ class IsolinesRoutingConfig(ServiceConfig): return 'mapzen_isolines' elif self._isolines_provider == self.MAPBOX_PROVIDER: return 'mapbox_isolines' + elif self._isolines_provider == self.MAPBOX_ISO_PROVIDER: + return 'mapbox_iso_isolines' elif self._isolines_provider == self.TOMTOM_PROVIDER: return 'tomtom_isolines' @@ -333,6 +339,18 @@ class IsolinesRoutingConfig(ServiceConfig): def mapbox_provider(self): return self._isolines_provider == self.MAPBOX_PROVIDER + @property + def mapbox_iso_isolines_api_keys(self): + return self._mapbox_iso_isolines_api_keys + + @property + def mapbox_iso_isolines_service_params(self): + return self._mapbox_iso_isolines_service_params + + @property + def mapbox_iso_provider(self): + return self._isolines_provider == self.MAPBOX_ISO_PROVIDER + @property def tomtom_isolines_api_keys(self): return self._tomtom_isolines_api_keys @@ -599,6 +617,7 @@ class ServicesDBConfig: self._get_here_config() self._get_mapzen_config() self._get_mapbox_config() + self._get_mapbox_iso_config() self._get_tomtom_config() self._get_data_observatory_config() @@ -663,6 +682,16 @@ class ServicesDBConfig: self._mapbox_geocoder_quota = mapbox_conf['geocoder']['monthly_quota'] self._mapbox_geocoder_service_params = mapbox_conf['geocoder'].get('service', {}) + def _get_mapbox_iso_config(self): + mapbox_iso_conf_json = self._get_conf('mapbox_iso_conf') + if not mapbox_iso_conf_json: + raise ConfigException('Mapbox True Isochrones configuration missing') + + mapbox_iso_conf = json.loads(mapbox_iso_conf_json) + self._mapbox_iso_isolines_api_keys = mapbox_conf['isolines']['api_keys'] + self._mapbox_iso_isolines_quota = tomtom_conf['isolines']['monthly_quota'] + self._mapbox_iso_isolines_service_params = tomtom_conf.get('isolines', {}).get('service', {}) + def _get_tomtom_config(self): tomtom_conf_json = self._get_conf('tomtom_conf') if not tomtom_conf_json: @@ -812,6 +841,18 @@ class ServicesDBConfig: def mapbox_geocoder_service_params(self): return self._mapbox_geocoder_service_params + @property + def mapbox_iso_isolines_api_keys(self): + return self._mapbox_iso_isolines_api_keys + + @property + def mapbox_iso_isolines_monthly_quota(self): + return self._mapbox_iso_isolines_quota + + @property + def mapbox_iso_isolines_service_params(self): + return self._mapbox_iso_isolines_service_params + @property def tomtom_isolines_api_keys(self): return self._tomtom_isolines_api_keys diff --git a/server/lib/python/cartodb_services/cartodb_services/metrics/user.py b/server/lib/python/cartodb_services/cartodb_services/metrics/user.py index 70bc9a3..d176183 100644 --- a/server/lib/python/cartodb_services/cartodb_services/metrics/user.py +++ b/server/lib/python/cartodb_services/cartodb_services/metrics/user.py @@ -22,6 +22,7 @@ class UserMetricsService: SERVICE_HERE_ISOLINES = 'here_isolines' SERVICE_MAPZEN_ISOLINES = 'mapzen_isolines' SERVICE_MAPBOX_ISOLINES = 'mapbox_isolines' + SERVICE_MAPBOX_ISO_ISOLINES = 'mapbox_iso_isolines' SERVICE_TOMTOM_ISOLINES = 'tomtom_isolines' SERVICE_MAPZEN_ROUTING = 'routing_mapzen' SERVICE_MAPBOX_ROUTING = 'routing_mapbox' @@ -39,6 +40,7 @@ class UserMetricsService: if service_type in [self.SERVICE_HERE_ISOLINES, self.SERVICE_MAPZEN_ISOLINES, self.SERVICE_MAPBOX_ISOLINES, + self.SERVICE_MAPBOX_ISO_ISOLINES, self.SERVICE_TOMTOM_ISOLINES]: return self.__used_isolines_quota(service_type, date) elif service_type in [self.SERVICE_MAPZEN_ROUTING, diff --git a/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py b/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py new file mode 100644 index 0000000..d0864f2 --- /dev/null +++ b/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py @@ -0,0 +1,123 @@ +from dateutil.parser import parse as date_parse +from cartodb_services.refactor.service.utils import round_robin +from cartodb_services.mapbox.types import MAPBOX_ISOLINES_APIKEY_ROUNDROBIN + + +class MapboxTrueIsolinesConfig(object): + """ + Configuration needed to operate the Mapbox directions service. + """ + + def __init__(self, + isolines_quota, + soft_isolines_limit, + period_end_date, + cost_per_hit, + log_path, + mapbox_api_keys, + username, + organization, + service_params, + GD): + self._isolines_quota = isolines_quota + self._soft_isolines_limit = soft_isolines_limit + self._period_end_date = period_end_date + self._cost_per_hit = cost_per_hit + self._log_path = log_path + self._mapbox_api_keys = mapbox_api_keys + self._username = username + self._organization = organization + self._service_params = service_params + self._GD = GD + + @property + def service_type(self): + return 'mapbox_isolines' + + @property + def provider(self): + return 'mapbox' + + @property + def is_high_resolution(self): + return True + + @property + def isolines_quota(self): + return self._isolines_quota + + @property + def soft_isolines_limit(self): + return self._soft_isolines_limit + + @property + def period_end_date(self): + return self._period_end_date + + @property + def cost_per_hit(self): + return self._cost_per_hit + + @property + def log_path(self): + return self._log_path + + @property + def mapbox_api_key(self): + return round_robin(self._mapbox_api_keys, self._GD, + MAPBOX_ISO_ISOLINES_APIKEY_ROUNDROBIN) + + @property + def username(self): + return self._username + + @property + def organization(self): + return self._organization + + @property + def service_params(self): + return self._service_params + + +class MapboxTrueIsolinesConfigBuilder(object): + + def __init__(self, server_conf, user_conf, org_conf, username, orgname, GD): + self._server_conf = server_conf + self._user_conf = user_conf + self._org_conf = org_conf + self._username = username + self._orgname = orgname + self._GD = GD + + def get(self): + mapbox_server_conf = self._server_conf.get('mapbox_iso_conf') + mapbox_api_keys = mapbox_server_conf['isolines']['api_keys'] + mapbox_service_params = mapbox_server_conf['isolines'].get('service', {}) + + isolines_quota = self._get_quota() + soft_isolines_limit = self._user_conf.get('soft_here_isolines_limit').lower() == 'true' + cost_per_hit = 0 + period_end_date_str = self._org_conf.get('period_end_date') or self._user_conf.get('period_end_date') + period_end_date = date_parse(period_end_date_str) + + logger_conf = self._server_conf.get('logger_conf') + log_path = logger_conf.get('isolines_log_path', None) + + return MapboxTrueIsolinesConfig(isolines_quota, + soft_isolines_limit, + period_end_date, + cost_per_hit, + log_path, + mapbox_api_keys, + self._username, + self._orgname, + mapbox_service_params, + self._GD) + + def _get_quota(self): + isolines_quota = self._org_conf.get('here_isolines_quota') or self._user_conf.get('here_isolines_quota') + if isolines_quota is '': + return 0 + + return int(isolines_quota) diff --git a/server/lib/python/cartodb_services/setup.py b/server/lib/python/cartodb_services/setup.py index 4a272ce..b355eae 100644 --- a/server/lib/python/cartodb_services/setup.py +++ b/server/lib/python/cartodb_services/setup.py @@ -10,7 +10,7 @@ from setuptools import setup, find_packages setup( name='cartodb_services', - version='0.21.4', + version='0.23.0', description='CartoDB Services API Python Library', diff --git a/server/lib/python/cartodb_services/test/metrics/test_config.py b/server/lib/python/cartodb_services/test/metrics/test_config.py index bf7d6b5..f2afd1c 100644 --- a/server/lib/python/cartodb_services/test/metrics/test_config.py +++ b/server/lib/python/cartodb_services/test/metrics/test_config.py @@ -174,7 +174,7 @@ class TestGeocoderOrgConfig(TestCase): class TestIsolinesUserConfig(TestCase): # Don't test mapbox. See CartoDB/cartodb-management/issues/5199" - ISOLINES_PROVIDERS = ['heremaps', 'mapzen', 'tomtom'] + ISOLINES_PROVIDERS = ['heremaps', 'mapzen', 'tomtom', 'mapbox_iso'] def setUp(self): self.redis_conn = MockRedis() @@ -190,6 +190,8 @@ class TestIsolinesUserConfig(TestCase): assert isolines_config.service_type is 'mapzen_isolines' elif isolines_provider is 'mapbox': assert isolines_config.service_type is 'mapbox_isolines' + elif isolines_provider is 'mapbox_iso': + assert isolines_config.service_type is 'mapbox_iso_isolines' elif isolines_provider is 'tomtom': assert isolines_config.service_type is 'tomtom_isolines' else: diff --git a/server/lib/python/cartodb_services/test/test_helper.py b/server/lib/python/cartodb_services/test/test_helper.py index dcdbbf5..9052354 100644 --- a/server/lib/python/cartodb_services/test/test_helper.py +++ b/server/lib/python/cartodb_services/test/test_helper.py @@ -77,6 +77,7 @@ def plpy_mock_config(): plpy_mock._define_result("CDB_Conf_GetConf\('heremaps_conf'\)", [{'conf': '{"geocoder": {"app_id": "app_id", "app_code": "code", "geocoder_cost_per_hit": 1}, "isolines": {"app_id": "app_id", "app_code": "code"}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('mapzen_conf'\)", [{'conf': '{"routing": {"api_key": "api_key_rou", "monthly_quota": 1500000}, "geocoder": {"api_key": "api_key_geo", "monthly_quota": 1500000}, "matrix": {"api_key": "api_key_mat", "monthly_quota": 1500000}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('mapbox_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) + plpy_mock._define_result("CDB_Conf_GetConf\('mapbox_iso_conf'\)", [{'conf': '{"isolines": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('tomtom_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('logger_conf'\)", [{'conf': '{"geocoder_log_path": "/dev/null"}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('data_observatory_conf'\)", [{'conf': '{"connection": {"whitelist": ["ethervoid"], "production": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api", "staging": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api"}}'}]) diff --git a/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py b/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py new file mode 100644 index 0000000..cc9dd9c --- /dev/null +++ b/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py @@ -0,0 +1,33 @@ +import unittest +from mock import Mock +from cartodb_services.mapbox.true_isolines import MapboxTrueIsolines, DEFAULT_PROFILE +from cartodb_services.tools import Coordinate + +from credentials import mapbox_api_key + +VALID_ORIGIN = Coordinate(-73.989, 40.733) + + +class MapboxTrueIsolinesTestCase(unittest.TestCase): + + def setUp(self): + self.mapbox_isolines = MapboxTrueIsolines(apikey=mapbox_api_key(), + logger=Mock()) + + def test_calculate_isochrone(self): + time_ranges = [300, 900] + solution = self.mapbox_isolines.calculate_isochrone( + origin=VALID_ORIGIN, + profile=DEFAULT_PROFILE, + time_ranges=time_ranges) + + assert solution + + def test_calculate_isodistance(self): + distance_range = 10000 + solution = self.mapbox_isolines.calculate_isodistance( + origin=VALID_ORIGIN, + profile=DEFAULT_PROFILE, + distance_range=distance_range) + + assert solution diff --git a/server/lib/python/cartodb_services/test/test_quota_service.py b/server/lib/python/cartodb_services/test/test_quota_service.py index ce1ca21..9c95dc1 100644 --- a/server/lib/python/cartodb_services/test/test_quota_service.py +++ b/server/lib/python/cartodb_services/test/test_quota_service.py @@ -178,6 +178,23 @@ class TestQuotaService(TestCase): qs.increment_isolines_service_use(amount=1500000) assert qs.check_user_quota() is False + def test_should_check_user_mapbox_iso_isolines_quota_correctly(self): + qs = self.__build_isolines_quota_service('test_user', + provider='mapbox_iso') + qs.increment_isolines_service_use() + assert qs.check_user_quota() is True + qs.increment_isolines_service_use(amount=1500000) + assert qs.check_user_quota() is False + + def test_should_check_org_mapbox_iso_isolines_quota_correctly(self): + qs = self.__build_isolines_quota_service('test_user', + provider='mapbox_iso', + orgname='testorg') + qs.increment_isolines_service_use() + assert qs.check_user_quota() is True + qs.increment_isolines_service_use(amount=1500000) + assert qs.check_user_quota() is False + # Quick workaround so we don't take into account numer of credits # spent for users that have defined the quota. # See https://github.com/CartoDB/bigmetadata/issues/215 From 3b5f33503b90ff2aba8ca405f1424a99c346f355 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Fri, 7 Feb 2020 15:52:31 +0100 Subject: [PATCH 04/20] Server extension changes --- README.md | 9 + ...db_dataservices_server--0.36.0--0.37.0.sql | 233 + ...db_dataservices_server--0.37.0--0.36.0.sql | 83 + .../cdb_dataservices_server--0.37.0.sql | 4043 +++++++++++++++++ .../extension/cdb_dataservices_server.control | 2 +- ...db_dataservices_server--0.35.1--0.36.0.sql | 0 ...db_dataservices_server--0.36.0--0.35.1.sql | 0 .../cdb_dataservices_server--0.36.0.sql | 0 .../test/expected/00_install_test.out | 6 + server/extension/test/sql/00_install_test.sql | 1 + 10 files changed, 4376 insertions(+), 1 deletion(-) create mode 100644 server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql create mode 100644 server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql create mode 100644 server/extension/cdb_dataservices_server--0.37.0.sql rename server/extension/{ => old_versions}/cdb_dataservices_server--0.35.1--0.36.0.sql (100%) rename server/extension/{ => old_versions}/cdb_dataservices_server--0.36.0--0.35.1.sql (100%) rename server/extension/{ => old_versions}/cdb_dataservices_server--0.36.0.sql (100%) diff --git a/README.md b/README.md index 72be30b..a06ebcf 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,15 @@ SELECT CDB_Conf_SetConf( ); ``` +#### Mapbox true isolines configuration + +```sql +SELECT CDB_Conf_SetConf( + 'mapbox_iso_conf', + '{"isolines": {"api_keys": ["your_api_key"], "monthly_quota": 1500000}}' +); +``` + #### TomTom configuration ```sql diff --git a/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql b/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql new file mode 100644 index 0000000..c1fb862 --- /dev/null +++ b/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql @@ -0,0 +1,233 @@ +--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES +-- Complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.37.0'" to load this file. \quit + +-- HERE goes your code to upgrade/downgrade + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxTrueIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapbox_iso_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox true isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox true isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxTrueIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + resp = mapbox_iso_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox true isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox true isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + if user_isolines_config.google_services_user: + raise Exception('This service is not available for google service users.') + + params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + + with metrics('cdb_isodistance', user_isolines_config, logger, params): + if user_isolines_config.heremaps_provider: + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_iso_provider: + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + else: + raise Exception('Requested isolines provider is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + if user_isolines_config.google_services_user: + raise Exception('This service is not available for google service users.') + + params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + + with metrics('cdb_isochrone', user_isolines_config, logger, params): + if user_isolines_config.heremaps_provider: + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_iso_provider: + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + else: + raise Exception('Requested isolines provider is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; diff --git a/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql b/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql new file mode 100644 index 0000000..3352fb4 --- /dev/null +++ b/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql @@ -0,0 +1,83 @@ +--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES +-- Complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.36.0'" to load this file. \quit + +-- HERE goes your code to upgrade/downgrade + +DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_iso_isodistance; + +DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_iso_isochrones; + +DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_mapbox_iso_isodistance; + +DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_mapbox_iso_isochrone; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + if user_isolines_config.google_services_user: + raise Exception('This service is not available for google service users.') + + params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + + with metrics('cdb_isodistance', user_isolines_config, logger, params): + if user_isolines_config.heremaps_provider: + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + else: + raise Exception('Requested isolines provider is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + if user_isolines_config.google_services_user: + raise Exception('This service is not available for google service users.') + + params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + + with metrics('cdb_isochrone', user_isolines_config, logger, params): + if user_isolines_config.heremaps_provider: + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + else: + raise Exception('Requested isolines provider is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; diff --git a/server/extension/cdb_dataservices_server--0.37.0.sql b/server/extension/cdb_dataservices_server--0.37.0.sql new file mode 100644 index 0000000..564e3d3 --- /dev/null +++ b/server/extension/cdb_dataservices_server--0.37.0.sql @@ -0,0 +1,4043 @@ +--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_server" to load this file. \quit +CREATE TYPE cdb_dataservices_server.simple_route AS ( + shape geometry(LineString,4326), + length real, + duration integer +); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_route_with_waypoints( + username TEXT, + orgname TEXT, + waypoints geometry(Point, 4326)[], + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxRouting + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.polyline import polyline_to_linestring + from cartodb_services.tools.normalize import options_to_dict + from cartodb_services.refactor.service.mapbox_routing_config import MapboxRoutingConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('routing', MapboxRoutingConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + client = MapboxRouting(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if not waypoints or len(waypoints) < 2: + service_manager.logger.info("Empty origin or destination") + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + + if len(waypoints) > 25: + service_manager.logger.info("Too many waypoints (max 25)") + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + + waypoint_coords = [] + for waypoint in waypoints: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon'] + waypoint_coords.append(Coordinate(lon,lat)) + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + options_dict = options_to_dict(options) + if 'mode_type' in options_dict: + plpy.warning('Mapbox provider doesnt support route type parameter') + + resp = client.directions(waypoint_coords, profile) + if resp and resp.shape: + shape_linestring = polyline_to_linestring(resp.shape) + if shape_linestring: + service_manager.quota_service.increment_success_service_use() + return [shape_linestring, resp.length, int(round(resp.duration))] + else: + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + else: + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to calculate Mapbox routing', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to calculate Mapbox routing') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoints( + username TEXT, + orgname TEXT, + waypoints geometry(Point, 4326)[], + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.tomtom import TomTomRouting + from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM, DEFAULT_ROUTE_TYPE, MODE_TYPE_TO_TOMTOM + from cartodb_services.tools import Coordinate + from cartodb_services.tools.polyline import polyline_to_linestring + from cartodb_services.tools.normalize import options_to_dict + from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('routing', TomTomRoutingConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + client = TomTomRouting(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + + if not waypoints or len(waypoints) < 2: + service_manager.logger.info("Empty origin or destination") + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + + if len(waypoints) > 25: + service_manager.logger.info("Too many waypoints (max 25)") + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + + waypoint_coords = [] + for waypoint in waypoints: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon'] + waypoint_coords.append(Coordinate(lon,lat)) + + profile = TRANSPORT_MODE_TO_TOMTOM.get(mode) + route_type = DEFAULT_ROUTE_TYPE + options_dict = options_to_dict(options) + if 'mode_type' in options_dict: + route_type = MODE_TYPE_TO_TOMTOM.get(options_dict['mode_type']) + + resp = client.directions(waypoint_coords, profile=profile, route_type=route_type) + if resp and resp.shape: + shape_linestring = polyline_to_linestring(resp.shape) + if shape_linestring: + service_manager.quota_service.increment_success_service_use() + return [shape_linestring, resp.length, int(round(resp.duration))] + else: + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + else: + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to calculate TomTom routing', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to calculate TomTom routing') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_route_with_waypoints( + username TEXT, + orgname TEXT, + waypoints geometry(Point, 4326)[], + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + import json + from cartodb_services.mapzen import MapzenRouting, MapzenRoutingResponse + from cartodb_services.mapzen.types import polyline_to_linestring + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Coordinate + from cartodb_services.tools import Logger,LoggerConfig + + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + user_routing_config = GD["user_routing_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + quota_service = QuotaService(user_routing_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + try: + client = MapzenRouting(user_routing_config.mapzen_api_key, logger, user_routing_config.mapzen_service_params) + + if not waypoints or len(waypoints) < 2: + logger.info("Empty origin or destination") + quota_service.increment_empty_service_use() + return [None, None, None] + + waypoint_coords = [] + for waypoint in waypoints: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon'] + waypoint_coords.append(Coordinate(lon,lat)) + + resp = client.calculate_route_point_to_point(waypoint_coords, mode, options, units) + if resp and resp.shape: + shape_linestring = polyline_to_linestring(resp.shape) + if shape_linestring: + quota_service.increment_success_service_use() + return [shape_linestring, resp.length, resp.duration] + else: + quota_service.increment_empty_service_use() + return [None, None, None] + else: + quota_service.increment_empty_service_use() + return [None, None, None] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to calculate mapzen routing', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to calculate mapzen routing') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point( + username TEXT, + orgname TEXT, + origin geometry(Point, 4326), + destination geometry(Point, 4326), + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_routing_config = GD["user_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + params = {'username': username, 'orgname': orgname, 'origin': origin, 'destination': destination, 'mode': mode, 'options': options, 'units': units} + + with metrics('cdb_route_with_point', user_routing_config, logger, params): + waypoints = [origin, destination] + + if user_routing_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + elif user_routing_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + elif user_routing_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + else: + raise Exception('Requested routing method is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints( + username TEXT, + orgname TEXT, + waypoints geometry(Point, 4326)[], + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_routing_config = GD["user_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + params = {'username': username, 'orgname': orgname, 'waypoints': waypoints, 'mode': mode, 'options': options, 'units': units} + + with metrics('cdb_route_with_waypoints', user_routing_config, logger, params): + if user_routing_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + elif user_routing_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + elif user_routing_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + else: + raise Exception('Requested routing method is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +-- 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, RedisDBConfig + metadata_config = RedisDBConfig('redis_metadata_config', plpy) + metrics_config = RedisDBConfig('redis_metrics_config', plpy) + redis_metadata_connection = RedisConnection(metadata_config).redis_connection() + redis_metrics_connection = RedisConnection(metrics_config).redis_connection() + GD[cache_key] = { + 'redis_metadata_connection': redis_metadata_connection, + 'redis_metrics_connection': redis_metrics_connection, + } + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +-- +-- Observatory connection config +-- +-- The purpose of this function is provide to the PL/Proxy functions +-- the connection string needed to connect with the current production database + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._obs_server_conn_str( + username TEXT, + orgname TEXT) +RETURNS text 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_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + return user_obs_config.connection_str +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetDemographicSnapshotJSON( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL, + geometry_level TEXT DEFAULT NULL) +RETURNS json AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetDemographicSnapshot(geom, time_span, geometry_level); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_get_demographic_snapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL, + geometry_level TEXT DEFAULT NULL) +RETURNS json AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + import json + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getdemographicsnapshot', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshotJSON($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level]) + if result: + quota_service.increment_success_service_use() + return result[0]['snapshot'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to obs_get_demographic_snapshot') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetDemographicSnapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL, + geometry_level TEXT DEFAULT NULL) +RETURNS SETOF json AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetDemographicSnapshot(geom, time_span, geometry_level); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetDemographicSnapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL, + geometry_level TEXT DEFAULT NULL) +RETURNS SETOF JSON AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getdemographicsnapshot', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshot($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level]) + if result: + resp = [] + for element in result: + value = element['snapshot'] + resp.append(value) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to obs_get_demographic_snapshot') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetSegmentSnapshotJSON( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + geometry_level TEXT DEFAULT NULL) +RETURNS json AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetSegmentSnapshot(geom, geometry_level); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_get_segment_snapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + geometry_level TEXT DEFAULT NULL) +RETURNS json AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + import json + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getsegmentsnapshot', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetSegmentSnapshotJSON($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level]) + if result: + quota_service.increment_success_service_use() + return result[0]['snapshot'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to obs_get_segment_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to obs_get_segment_snapshot') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetSegmentSnapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + geometry_level TEXT DEFAULT NULL) +RETURNS SETOF json AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetSegmentSnapshot(geom, geometry_level); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetSegmentSnapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + geometry_level TEXT DEFAULT NULL) +RETURNS SETOF JSON AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getsegmentsnapshot', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetSegmentSnapshot($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level]) + if result: + resp = [] + for element in result: + value = element['snapshot'] + resp.append(value) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetSegmentSnapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetSegmentSnapshot') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeasure( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + measure_id TEXT, + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetMeasure(geom, measure_id, normalize, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeasure( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + measure_id TEXT, + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getmeasure', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasure($1, $2, $3, $4, $5, $6, $7) as measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, measure_id, normalize, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['measure'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetMeasure', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetMeasure') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetCategory( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + category_id TEXT, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetCategory(geom, category_id, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetCategory( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + category_id TEXT, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getcategory', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetCategory($1, $2, $3, $4, $5, $6) as category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, category_id, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['category'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetCategory', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetCategory') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetUSCensusMeasure( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + name TEXT, + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetUSCensusMeasure(geom, name, normalize, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetUSCensusMeasure( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + name TEXT, + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getuscensusmeasure', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusMeasure($1, $2, $3, $4, $5, $6, $7) as census_measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, name, normalize, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['census_measure'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetUSCensusMeasure', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetUSCensusMeasure') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetUSCensusCategory( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + name TEXT, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetUSCensusCategory(geom, name, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetUSCensusCategory( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + name TEXT, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getuscensuscategory', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusCategory($1, $2, $3, $4, $5, $6) as census_category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, name, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['census_category'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetUSCensusCategory', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetUSCensusCategory') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPopulation( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetPopulation(geom, normalize, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPopulation( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getpopulation', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetPopulation($1, $2, $3, $4, $5, $6) as population;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, normalize, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['population'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetPopulation', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetPopulation') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeasureById( + username TEXT, + orgname TEXT, + geom_ref TEXT, + measure_id TEXT, + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetMeasureById(geom_ref, measure_id, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeasureById( + username TEXT, + orgname TEXT, + geom_ref TEXT, + measure_id TEXT, + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getmeasurebyid', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasureById($1, $2, $3, $4, $5, $6) as measure;", ["text", "text", "text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom_ref, measure_id, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['measure'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetMeasureById') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData( + username TEXT, + orgname TEXT, + geomvals geomval[], + params JSON, + merge BOOLEAN DEFAULT True) +RETURNS TABLE ( + id INT, + data JSON +) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetData(geomvals, params, merge); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData( + username TEXT, + orgname TEXT, + geomvals geomval[], + params JSON, + merge BOOLEAN DEFAULT True) +RETURNS TABLE ( + id INT, + data JSON +) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getdata', user_obs_config, logger, params): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4, $5);", ["text", "text", "geomval[]", "json", "boolean"]) + result = plpy.execute(obs_plan, [username, orgname, geomvals, params, merge]) + empty_results = len(geomvals) - len(result) + if empty_results > 0: + quota_service.increment_empty_service_use(empty_results) + if result: + quota_service.increment_success_service_use(len(result)) + return result + else: + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use(len(geomvals)) + logger.error('Error trying to OBS_GetData', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetData') + finally: + quota_service.increment_total_service_use(len(geomvals)) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData( + username TEXT, + orgname TEXT, + geomrefs TEXT[], + params JSON) +RETURNS TABLE ( + id TEXT, + data JSON +) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetData(geomrefs, params); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData( + username TEXT, + orgname TEXT, + geomrefs TEXT[], + params JSON) +RETURNS TABLE ( + id TEXT, + data JSON +) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getdata', user_obs_config, logger, params): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4);", ["text", "text", "text[]", "json"]) + result = plpy.execute(obs_plan, [username, orgname, geomrefs, params]) + empty_results = len(geomrefs) - len(result) + if empty_results > 0: + quota_service.increment_empty_service_use(empty_results) + if result: + quota_service.increment_success_service_use(len(result)) + return result + else: + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use(len(geomrefs)) + exc_info = sys.exc_info() + logger.error('%s, %s, %s' % (exc_info[0], exc_info[1], exc_info[2])) + logger.error('Error trying to OBS_GetData', exc_info, data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetData') + finally: + quota_service.increment_total_service_use(len(geomrefs)) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeta( + username TEXT, + orgname TEXT, + geom Geometry(Geometry, 4326), + params JSON, + max_timespan_rank INTEGER DEFAULT NULL, + max_score_rank INTEGER DEFAULT NULL, + target_geoms INTEGER DEFAULT NULL) +RETURNS JSON AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetMeta(geom, params, max_timespan_rank, max_score_rank, target_geoms); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeta( + username TEXT, + orgname TEXT, + geom Geometry(Geometry, 4326), + params JSON, + max_timespan_rank INTEGER DEFAULT NULL, + max_score_rank INTEGER DEFAULT NULL, + target_geoms INTEGER DEFAULT NULL) +RETURNS JSON AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + with metrics('obs_getmeta', user_obs_config, logger, params): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeta($1, $2, $3, $4, $5, $6, $7) as meta;", ["text", "text", "Geometry (Geometry, 4326)", "json", "integer", "integer", "integer"]) + result = plpy.execute(obs_plan, [username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms]) + if result: + return result[0]['meta'] + else: + return None + except BaseException as e: + import sys + logger.error('Error trying to OBS_GetMeta', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetMeta') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_MetadataValidation( + username TEXT, + orgname TEXT, + geometry_extent Geometry(Geometry, 4326), + geometry_type text, + params JSON, + target_geoms INTEGER DEFAULT NULL) +RETURNS TABLE(valid boolean, errors text[]) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_MetadataValidation(geometry_extent, geometry_type, params, target_geoms); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_MetadataValidation( + username TEXT, + orgname TEXT, + geometry_extent Geometry(Geometry, 4326), + geometry_type text, + params JSON, + target_geoms INTEGER DEFAULT NULL) +RETURNS TABLE(valid boolean, errors text[]) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + with metrics('obs_metadatavalidation', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_MetadataValidation($1, $2, $3, $4, $5, $6);", ["text", "text", "Geometry (Geometry, 4326)", "text", "json", "integer"]) + result = plpy.execute(obs_plan, [username, orgname, geometry_extent, geometry_type, params, target_geoms]) + if result: + return result + else: + return [] + except BaseException as e: + import sys + logger.error('Error trying to OBS_MetadataValidation', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_MetadataValidation') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_Search( + username TEXT, + orgname TEXT, + search_term TEXT, + relevant_boundary TEXT DEFAULT NULL) +RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_Search(search_term, relevant_boundary); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_Search( + username TEXT, + orgname TEXT, + search_term TEXT, + relevant_boundary TEXT DEFAULT NULL) +RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_search', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_Search($1, $2, $3, $4);", ["text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, search_term, relevant_boundary]) + if result: + resp = [] + for element in result: + id = element['id'] + description = element['description'] + name = element['name'] + aggregate = element['aggregate'] + source = element['source'] + resp.append([id, description, name, aggregate, source]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [None, None, None, None, None] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_Search', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_Search') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetAvailableBoundaries( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL) +RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableBoundaries(geom, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableBoundaries( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL) +RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getavailableboundaries', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetAvailableBoundaries($1, $2, $3, $4) as available_boundaries;", ["text", "text", "geometry(Geometry, 4326)", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, time_span]) + if result: + resp = [] + for element in result: + id = element['boundary_id'] + description = element['description'] + tspan = element['time_span'] + tablename = element['tablename'] + resp.append([id, description, tspan, tablename]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetMeasureById') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundary( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS geometry(Geometry, 4326) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetBoundary(geom, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundary( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS geometry(Geometry, 4326) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundary', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundary($1, $2, $3, $4) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['boundary'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundary', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundary') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundaryId( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetBoundaryId(geom, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundaryId( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundaryid', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryId($1, $2, $3, $4, $5) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['boundary'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundaryId', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundaryId') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundaryById( + username TEXT, + orgname TEXT, + geometry_id TEXT, + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS geometry(Geometry, 4326) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetBoundaryById(geometry_id, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundaryById( + username TEXT, + orgname TEXT, + geometry_id TEXT, + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS geometry(Geometry, 4326) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundarybyid', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryById($1, $2, $3, $4, $5) as boundary;", ["text", "text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geometry_id, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['boundary'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundaryById', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundaryById') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundariesByGeometry( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetBoundariesByGeometry(geom, boundary_id, time_span, overlap_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundariesByGeometry( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundariesbygeometry', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type]) + if result: + resp = [] + for element in result: + the_geom = element['the_geom'] + geom_refs = element['geom_refs'] + resp.append([the_geom, geom_refs]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundariesByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundariesByGeometry') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundariesByPointAndRadius( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + radius NUMERIC, + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetBoundariesByPointAndRadius(geom, radius, boundary_id, time_span, overlap_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundariesByPointAndRadius( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + radius NUMERIC, + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundariesbypointandradius', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type]) + if result: + resp = [] + for element in result: + the_geom = element['the_geom'] + geom_refs = element['geom_refs'] + resp.append([the_geom, geom_refs]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundariesByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundariesByPointAndRadius') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPointsByGeometry( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetPointsByGeometry(geom, boundary_id, time_span, overlap_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPointsByGeometry( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getpointsbygeometry', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type]) + if result: + resp = [] + for element in result: + the_geom = element['the_geom'] + geom_refs = element['geom_refs'] + resp.append([the_geom, geom_refs]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetPointsByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetPointsByGeometry') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPointsByPointAndRadius( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + radius NUMERIC, + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetPointsByPointAndRadius(geom, radius, boundary_id, time_span, overlap_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPointsByPointAndRadius( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + radius NUMERIC, + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getpointsbypointandradius', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type]) + if result: + resp = [] + for element in result: + the_geom = element['the_geom'] + geom_refs = element['geom_refs'] + resp.append([the_geom, geom_refs]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetPointsByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetPointsByPointAndRadius') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE TYPE cdb_dataservices_server.ds_fdw_metadata as (schemaname text, tabname text, servername text); + +CREATE TYPE cdb_dataservices_server.ds_return_metadata as (colnames text[], coltypes text[]); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_ConnectUserTable(username text, orgname text, user_db_role text, input_schema text, dbname text, table_name text) +RETURNS cdb_dataservices_server.ds_fdw_metadata AS $$ + host_addr = plpy.execute("SELECT split_part(inet_client_addr()::text, '/', 1) as user_host")[0]['user_host'] + return plpy.execute("SELECT * FROM cdb_dataservices_server.__DST_ConnectUserTable({username}::text, {orgname}::text, {user_db_role}::text, {schema}::text, {dbname}::text, {host_addr}::text, {table_name}::text)" + .format(username=plpy.quote_nullable(username), orgname=plpy.quote_nullable(orgname), user_db_role=plpy.quote_literal(user_db_role), schema=plpy.quote_literal(input_schema), dbname=plpy.quote_literal(dbname), table_name=plpy.quote_literal(table_name), host_addr=plpy.quote_literal(host_addr)) + )[0] +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.__DST_ConnectUserTable(username text, orgname text, user_db_role text, input_schema text, dbname text, host_addr text, table_name text) +RETURNS cdb_dataservices_server.ds_fdw_metadata AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + TARGET cdb_observatory._OBS_ConnectUserTable; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_GetReturnMetadata(username text, orgname text, function_name text, params json) +RETURNS cdb_dataservices_server.ds_return_metadata AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + TARGET cdb_observatory._OBS_GetReturnMetadata; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_FetchJoinFdwTableData(username text, orgname text, table_schema text, table_name text, function_name text, params json) +RETURNS SETOF record AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + TARGET cdb_observatory._OBS_FetchJoinFdwTableData; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_DisconnectUserTable(username text, orgname text, table_schema text, table_name text, servername text) +RETURNS boolean AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + TARGET cdb_observatory._OBS_DisconnectUserTable; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_dumpversion(username text, orgname text) +RETURNS text AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.obs_dumpversion(); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +-- We could create a super type for the common data like id, name and so on but we need to parse inside the functions because the -- the return data tha comes from OBS is a TABLE() with them +CREATE TYPE cdb_dataservices_server.obs_meta_numerator AS (numer_id text, numer_name text, numer_description text, numer_weight text, numer_license text, numer_source text, numer_type text, numer_aggregate text, numer_extra jsonb, numer_tags jsonb, valid_denom boolean, valid_geom boolean, valid_timespan boolean); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableNumerators( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + filter_tags TEXT[] DEFAULT NULL, + denom_id TEXT DEFAULT NULL, + geom_id TEXT DEFAULT NULL, + timespan TEXT DEFAULT NULL) +RETURNS SETOF cdb_dataservices_server.obs_meta_numerator AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableNumerators(bounds, filter_tags, denom_id, geom_id, timespan); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetNumerators( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + section_tags TEXT[] DEFAULT ARRAY[]::TEXT[], + subsection_tags TEXT[] DEFAULT ARRAY[]::TEXT[], + other_tags TEXT[] DEFAULT ARRAY[]::TEXT[], + ids TEXT[] DEFAULT ARRAY[]::TEXT[], + name TEXT DEFAULT NULL, + denom_id TEXT DEFAULT '', + geom_id TEXT DEFAULT '', + timespan TEXT DEFAULT '') +RETURNS SETOF cdb_dataservices_server.obs_meta_numerator AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory._OBS_GetNumerators(bounds, section_tags, subsection_tags, other_tags, ids, name, denom_id, geom_id, timespan); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE TYPE cdb_dataservices_server.obs_meta_denominator AS (denom_id text, denom_name text, denom_description text, denom_weight text, denom_license text, denom_source text, denom_type text, denom_aggregate text, denom_extra jsonb, denom_tags jsonb, valid_numer boolean, valid_geom boolean, valid_timespan boolean); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableDenominators( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + filter_tags TEXT[] DEFAULT NULL, + numer_id TEXT DEFAULT NULL, + geom_id TEXT DEFAULT NULL, + timespan TEXT DEFAULT NULL) +RETURNS SETOF cdb_dataservices_server.obs_meta_denominator AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableDenominators(bounds, filter_tags, numer_id, geom_id, timespan); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE TYPE cdb_dataservices_server.obs_meta_geometry AS (geom_id text, geom_name text, geom_description text, geom_weight text, geom_aggregate text, geom_license text, geom_source text, valid_numer boolean, valid_denom boolean, valid_timespan boolean, score numeric, numtiles bigint, notnull_percent numeric, numgeoms numeric, percentfill numeric, estnumgeoms numeric, meanmediansize numeric, geom_type text, geom_extra jsonb, geom_tags jsonb); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableGeometries( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + filter_tags TEXT[] DEFAULT NULL, + numer_id TEXT DEFAULT NULL, + denom_id TEXT DEFAULT NULL, + timespan TEXT DEFAULT NULL, + number_geometries INTEGER DEFAULT NULL) +RETURNS SETOF cdb_dataservices_server.obs_meta_geometry AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableGeometries(bounds, filter_tags, numer_id, denom_id, timespan, number_geometries); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE TYPE cdb_dataservices_server.obs_meta_timespan AS (timespan_id text, timespan_name text, timespan_description text, timespan_weight text, timespan_aggregate text, timespan_license text, timespan_source text, valid_numer boolean, valid_denom boolean, valid_geom boolean, timespan_type text, timespan_extra jsonb, timespan_tags jsonb); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableTimespans( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + filter_tags TEXT[] DEFAULT NULL, + numer_id TEXT DEFAULT NULL, + denom_id TEXT DEFAULT NULL, + geom_id TEXT DEFAULT NULL) +RETURNS SETOF cdb_dataservices_server.obs_meta_timespan AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableTimespans(bounds, filter_tags, numer_id, denom_id, geom_id); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_LegacyBuilderMetadata( + username TEXT, + orgname TEXT, + aggregate_type TEXT DEFAULT NULL) +RETURNS TABLE(name TEXT, subsection JSON) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_LegacyBuilderMetadata(aggregate_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_logger_config() +RETURNS boolean AS $$ + cache_key = "logger_config" + if cache_key in GD: + return False + else: + from cartodb_services.tools import LoggerConfig + logger_config = LoggerConfig(plpy) + GD[cache_key] = logger_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +-- This is done in order to avoid an undesired depedency on cartodb extension +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_conf_getconf(input_key text) +RETURNS JSON AS $$ + SELECT VALUE FROM cartodb.cdb_conf WHERE key = input_key; +$$ LANGUAGE SQL SECURITY DEFINER STABLE PARALLEL SAFE; + +CREATE OR REPLACE +FUNCTION cdb_dataservices_server.CDB_Conf_SetConf(key text, value JSON) + RETURNS void AS $$ +BEGIN + PERFORM cdb_dataservices_server.CDB_Conf_RemoveConf(key); + EXECUTE 'INSERT INTO cartodb.CDB_CONF (KEY, VALUE) VALUES ($1, $2);' USING key, value; +END +$$ LANGUAGE PLPGSQL SECURITY DEFINER VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE +FUNCTION cdb_dataservices_server.CDB_Conf_RemoveConf(key text) + RETURNS void AS $$ +BEGIN + EXECUTE 'DELETE FROM cartodb.CDB_CONF WHERE KEY = $1;' USING key; +END +$$ LANGUAGE PLPGSQL SECURITY DEFINER VOLATILE PARALLEL UNSAFE ; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_geocoder_config(username text, orgname text, provider text DEFAULT NULL) +RETURNS boolean AS $$ + cache_key = "user_geocoder_config_{0}".format(username) + if cache_key in GD: + return False + else: + 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'] + geocoder_config = GeocoderConfig(redis_conn, plpy, username, orgname, provider) + GD[cache_key] = geocoder_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_internal_geocoder_config(username text, orgname text) +RETURNS boolean AS $$ + cache_key = "user_internal_geocoder_config_{0}".format(username) + if cache_key in GD: + return False + else: + from cartodb_services.metrics import InternalGeocoderConfig + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection'] + geocoder_config = InternalGeocoderConfig(redis_conn, plpy, username, orgname) + GD[cache_key] = geocoder_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +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: + 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'] + isolines_routing_config = IsolinesRoutingConfig(redis_conn, plpy, username, orgname) + GD[cache_key] = isolines_routing_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +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: + 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'] + routing_config = RoutingConfig(redis_conn, plpy, username, orgname) + GD[cache_key] = routing_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_obs_config(username text, orgname text) +RETURNS boolean AS $$ + cache_key = "user_obs_config_{0}".format(username) + if cache_key in GD: + return False + else: + from cartodb_services.metrics import ObservatoryConfig + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection'] + obs_config = ObservatoryConfig(redis_conn, plpy, username, orgname) + GD[cache_key] = obs_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid) + WHERE pg_type.typname = 'service_type' + AND pg_namespace.nspname = 'cdb_dataservices_server') THEN + CREATE TYPE cdb_dataservices_server.service_type AS ENUM ( + 'isolines', + 'hires_geocoder', + 'routing', + 'observatory' + ); + END IF; +END $$; + +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid) + WHERE pg_type.typname = 'service_quota_info' + AND pg_namespace.nspname = 'cdb_dataservices_server') THEN + CREATE TYPE cdb_dataservices_server.service_quota_info AS ( + service cdb_dataservices_server.service_type, + monthly_quota NUMERIC, + used_quota NUMERIC, + soft_limit BOOLEAN, + provider TEXT + ); + END IF; +END $$; + +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid) + WHERE pg_type.typname = 'service_quota_info_batch' + AND pg_namespace.nspname = 'cdb_dataservices_server') THEN + CREATE TYPE cdb_dataservices_server.service_quota_info_batch AS ( + service cdb_dataservices_server.service_type, + monthly_quota NUMERIC, + used_quota NUMERIC, + soft_limit BOOLEAN, + provider TEXT, + max_batch_size NUMERIC + ); + END IF; +END $$; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info( + username TEXT, + orgname TEXT) +RETURNS SETOF cdb_dataservices_server.service_quota_info AS $$ + from cartodb_services.metrics.user import UserMetricsService + from datetime import date + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + + today = date.today() + ret = [] + + #-- Isolines + service = 'isolines' + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + user_service = UserMetricsService(user_isolines_config, redis_conn) + + monthly_quota = user_isolines_config.isolines_quota + used_quota = user_service.used_quota(user_isolines_config.service_type, today) + soft_limit = user_isolines_config.soft_isolines_limit + provider = user_isolines_config.provider + ret += [[service, monthly_quota, used_quota, soft_limit, provider]] + + #-- Hires Geocoder + service = 'hires_geocoder' + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + user_service = UserMetricsService(user_geocoder_config, redis_conn) + + monthly_quota = user_geocoder_config.geocoding_quota + used_quota = user_service.used_quota(user_geocoder_config.service_type, today) + soft_limit = user_geocoder_config.soft_geocoding_limit + provider = user_geocoder_config.provider + ret += [[service, monthly_quota, used_quota, soft_limit, provider]] + + #-- Routing + service = 'routing' + 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)] + user_service = UserMetricsService(user_routing_config, redis_conn) + + monthly_quota = user_routing_config.monthly_quota + used_quota = user_service.used_quota(user_routing_config.service_type, today) + soft_limit = user_routing_config.soft_limit + provider = user_routing_config.provider + ret += [[service, monthly_quota, used_quota, soft_limit, provider]] + + #-- Observatory + service = 'observatory' + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + user_service = UserMetricsService(user_obs_config, redis_conn) + + monthly_quota = user_obs_config.monthly_quota + used_quota = user_service.used_quota(user_obs_config.service_type, today) + soft_limit = user_obs_config.soft_limit + provider = user_obs_config.provider + ret += [[service, monthly_quota, used_quota, soft_limit, provider]] + + return ret +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info_batch( + username TEXT, + orgname TEXT) +RETURNS SETOF cdb_dataservices_server.service_quota_info_batch AS $$ + from cartodb_services.bulk_geocoders import BATCH_GEOCODER_CLASS_BY_PROVIDER + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + sqi = plpy.execute("SELECT * from cdb_dataservices_server.cdb_service_quota_info({0},{1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + + ret = [] + for info in sqi: + if info['service'] == 'hires_geocoder': + provider = info['provider'] + batch_geocoder_class = BATCH_GEOCODER_CLASS_BY_PROVIDER.get(provider, None) + if batch_geocoder_class and hasattr(batch_geocoder_class, 'MAX_BATCH_SIZE'): + max_batch_size = batch_geocoder_class.MAX_BATCH_SIZE + else: + max_batch_size = 1 + + info['max_batch_size'] = max_batch_size + else: + info['max_batch_size'] = 1 + + ret += [[info['service'], info['monthly_quota'], info['used_quota'], info['soft_limit'], info['provider'], info['max_batch_size']]] + + return ret +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_enough_quota( + username TEXT, + orgname TEXT, + service_ TEXT, + input_size NUMERIC) +returns BOOLEAN AS $$ + DECLARE + params cdb_dataservices_server.service_quota_info; + BEGIN + SELECT * INTO params + FROM cdb_dataservices_server.cdb_service_quota_info(username, orgname) AS p + WHERE p.service = service_::cdb_dataservices_server.service_type; + RETURN params.soft_limit OR ((params.used_quota + input_size) <= params.monthly_quota); + END +$$ LANGUAGE plpgsql STABLE PARALLEL RESTRICTED; +-- Geocodes a street address given a searchtext and a state and/or country + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger,LoggerConfig + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + params = {'username': username, 'orgname': orgname, 'searchtext': searchtext, 'city': city, 'state_province': state_province, 'country': country} + + with metrics('cdb_geocode_street_point', user_geocoder_config, logger, params): + if user_geocoder_config.heremaps_geocoder: + here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.google_geocoder: + google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.mapzen_geocoder: + mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.mapbox_geocoder: + mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.tomtom_geocoder: + tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.geocodio_geocoder: + geocodio_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocodio_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(geocodio_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + else: + raise Exception('Requested geocoder is not available') + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_here_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + if user_geocoder_config.heremaps_geocoder: + here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + else: + raise Exception('Here geocoder is not available for your account.') + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_google_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + if user_geocoder_config.google_geocoder: + google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + else: + raise Exception('Google geocoder is not available for your account.') + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + # The configuration is retrieved but no checks are performed on it + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + # The configuration is retrieved but no checks are performed on it + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + # The configuration is retrieved but no checks are performed on it + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocodio_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + # The configuration is retrieved but no checks are performed on it + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + geocodio_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocodio_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(geocodio_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.tools import LegacyServiceManager + from cartodb_services.tools import QuotaExceededException + from cartodb_services.here import HereMapsGeocoder + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + service_manager = LegacyServiceManager('geocoder', username, orgname, GD) + + try: + service_manager.assert_within_limits() + geocoder = HereMapsGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params) + coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using here maps', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using here maps') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_google_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.tools import LegacyServiceManager, QuotaExceededException + from cartodb_services.google import GoogleMapsGeocoder + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + service_manager = LegacyServiceManager('geocoder', username, orgname, GD) + + try: + service_manager.assert_within_limits(quota=False) + geocoder = GoogleMapsGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger) + coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using google maps', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using google maps') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.tools import ServiceManager, QuotaExceededException + from cartodb_services.mapzen import MapzenGeocoder + from cartodb_services.tools.country import country_to_iso3 + from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname) + + try: + service_manager.assert_within_limits() + geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params) + country_iso3 = None + if country: + country_iso3 = country_to_iso3(country) + coordinates = geocoder.geocode(searchtext=searchtext, city=city, + state_province=state_province, + country=country_iso3, search_type='address') + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using mapzen') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from iso3166 import countries + from cartodb_services.tools import ServiceManager, QuotaExceededException + from cartodb_services.mapbox import MapboxGeocoder + from cartodb_services.tools.country import country_to_iso3 + from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD) + + try: + service_manager.assert_within_limits() + geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + country_iso3166 = None + if country: + country_iso3 = country_to_iso3(country) + if country_iso3: + country_iso3166 = countries.get(country_iso3).alpha2.lower() + + coordinates = geocoder.geocode(searchtext=searchtext, city=city, + state_province=state_province, + country=country_iso3166) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using Mapbox', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using Mapbox') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from iso3166 import countries + from cartodb_services.tools import ServiceManager, QuotaExceededException + from cartodb_services.tomtom import TomTomGeocoder + from cartodb_services.tools.country import country_to_iso3 + from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD) + + try: + service_manager.assert_within_limits() + geocoder = TomTomGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + + country_iso3166 = None + if country: + country_iso3 = country_to_iso3(country) + if country_iso3: + country_iso3166 = countries.get(country_iso3).alpha2.lower() + + coordinates = geocoder.geocode(searchtext=searchtext, city=city, + state_province=state_province, + country=country_iso3166) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using TomTom', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using TomTom') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocodio_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from iso3166 import countries + from cartodb_services.tools import ServiceManager, QuotaExceededException + from cartodb_services.geocodio import GeocodioGeocoder + from cartodb_services.tools.country import country_to_iso3 + from cartodb_services.refactor.service.geocodio_geocoder_config import GeocodioGeocoderConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('geocoder', GeocodioGeocoderConfigBuilder, username, orgname, GD) + + try: + service_manager.assert_within_limits() + geocoder = GeocodioGeocoder(service_manager.config.geocodio_api_key, service_manager.logger, service_manager.config.service_params) + + country_iso3166 = None + if country: + country_iso3 = country_to_iso3(country) + if country_iso3: + country_iso3166 = countries.get(country_iso3).alpha2.lower() + + coordinates = geocoder.geocode(searchtext=searchtext, city=city, + state_province=state_province, + country=country_iso3166) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using Geocodio', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using Geocodio') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_get_rate_limit( + username TEXT, + orgname TEXT, + service TEXT) +RETURNS JSON AS $$ + import json + from cartodb_services.config import ServiceConfiguration, RateLimitsConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_config = ServiceConfiguration(service, username, orgname) + rate_limit_config = RateLimitsConfigBuilder(service_config.server, service_config.user, service_config.org, service=service, username=username, orgname=orgname).get() + if rate_limit_config.is_limited(): + return json.dumps({'limit': rate_limit_config.limit, 'period': rate_limit_config.period}) + else: + return None +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_set_user_rate_limit( + username TEXT, + orgname TEXT, + service TEXT, + rate_limit_json JSON) +RETURNS VOID AS $$ + import json + from cartodb_services.config import RateLimitsConfig, RateLimitsConfigSetter + + import cartodb_services + cartodb_services.init(plpy, GD) + + config_setter = RateLimitsConfigSetter(service=service, username=username, orgname=orgname) + if rate_limit_json: + rate_limit = json.loads(rate_limit_json) + limit = rate_limit.get('limit', None) + period = rate_limit.get('period', None) + else: + limit = None + period = None + config = RateLimitsConfig(service=service, username=username, limit=limit, period=period) + config_setter.set_user_rate_limits(config) +$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_set_org_rate_limit( + username TEXT, + orgname TEXT, + service TEXT, + rate_limit_json JSON) +RETURNS VOID AS $$ + import json + from cartodb_services.config import RateLimitsConfig, RateLimitsConfigSetter + + import cartodb_services + cartodb_services.init(plpy, GD) + + config_setter = RateLimitsConfigSetter(service=service, username=username, orgname=orgname) + if rate_limit_json: + rate_limit = json.loads(rate_limit_json) + limit = rate_limit.get('limit', None) + period = rate_limit.get('period', None) + else: + limit = None + period = None + config = RateLimitsConfig(service=service, username=username, limit=limit, period=period) + config_setter.set_org_rate_limits(config) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_set_server_rate_limit( + username TEXT, + orgname TEXT, + service TEXT, + rate_limit_json JSON) +RETURNS VOID AS $$ + import json + from cartodb_services.config import RateLimitsConfig, RateLimitsConfigSetter + + import cartodb_services + cartodb_services.init(plpy, GD) + + config_setter = RateLimitsConfigSetter(service=service, username=username, orgname=orgname) + if rate_limit_json: + rate_limit = json.loads(rate_limit_json) + limit = rate_limit.get('limit', None) + period = rate_limit.get('period', None) + else: + limit = None + period = None + config = RateLimitsConfig(service=service, username=username, limit=limit, period=period) + config_setter.set_server_rate_limits(config) +$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; +-- TODO: could cartodb_id be replaced by rowid, maybe needing extra care for offset? +CREATE TYPE cdb_dataservices_server.geocoding AS ( + cartodb_id integer, + the_geom geometry(Point,4326), + metadata jsonb +); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + import json + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + params = {'username': username, 'orgname': orgname, 'searches': json.loads(searches)} + + with metrics('cdb_bulk_geocode_street_point', user_geocoder_config, logger, params): + if user_geocoder_config.google_geocoder: + provider_function = "_cdb_bulk_google_geocode_street_point"; + elif user_geocoder_config.heremaps_geocoder: + provider_function = "_cdb_bulk_heremaps_geocode_street_point"; + elif user_geocoder_config.tomtom_geocoder: + provider_function = "_cdb_bulk_tomtom_geocode_street_point"; + elif user_geocoder_config.mapbox_geocoder: + provider_function = "_cdb_bulk_mapbox_geocode_street_point"; + elif user_geocoder_config.geocodio_geocoder: + provider_function = "_cdb_bulk_geocodio_geocode_street_point"; + else: + raise Exception('Requested geocoder is not available') + + plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.{}($1, $2, $3); ".format(provider_function), ["text", "text", "jsonb"]) + return plpy.execute(plan, [username, orgname, searches]) + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_google_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import LegacyServiceManager + from cartodb_services.google import GoogleMapsBulkGeocoder + + service_manager = LegacyServiceManager('geocoder', username, orgname, GD) + geocoder = GoogleMapsBulkGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_heremaps_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import LegacyServiceManager + from cartodb_services.here import HereMapsBulkGeocoder + + service_manager = LegacyServiceManager('geocoder', username, orgname, GD) + geocoder = HereMapsBulkGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_tomtom_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import ServiceManager + from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder + from cartodb_services.tomtom import TomTomBulkGeocoder + from cartodb_services.tools import Logger + import cartodb_services + cartodb_services.init(plpy, GD) + + logger_config = GD["logger_config"] + logger = Logger(logger_config) + service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD) + geocoder = TomTomBulkGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_mapbox_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import ServiceManager + from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder + from cartodb_services.mapbox import MapboxBulkGeocoder + from cartodb_services.tools import Logger + import cartodb_services + cartodb_services.init(plpy, GD) + + logger_config = GD["logger_config"] + logger = Logger(logger_config) + service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD) + geocoder = MapboxBulkGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocodio_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import ServiceManager + from cartodb_services.refactor.service.geocodio_geocoder_config import GeocodioGeocoderConfigBuilder + from cartodb_services.geocodio import GeocodioBulkGeocoder + from cartodb_services.tools import Logger + import cartodb_services + cartodb_services.init(plpy, GD) + + logger_config = GD["logger_config"] + logger = Logger(logger_config) + service_manager = ServiceManager('geocoder', GeocodioGeocoderConfigBuilder, username, orgname, GD) + geocoder = GeocodioBulkGeocoder(service_manager.config.geocodio_api_key, service_manager.logger, service_manager.config.service_params) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin0_polygon(username text, orgname text, country_name text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'country_name': country_name} + + with metrics('cdb_geocode_admin0_polygon', user_geocoder_config, logger, params): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin0_polygon(trim($1)) AS mypolygon", ["text"]) + rv = plpy.execute(plan, [country_name], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode admin0 polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode admin0 polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_admin0_polygon(country_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT n.the_geom as geom INTO ret + FROM (SELECT q, lower(regexp_replace(q, '[^a-zA-Z\u00C0-\u00ff]+', '', 'g'))::text x + FROM (SELECT country_name q) g) d + LEFT OUTER JOIN admin0_synonyms s ON name_ = d.x + LEFT OUTER JOIN ne_admin0_v3 n ON s.adm0_a3 = n.adm0_a3 GROUP BY d.q, n.the_geom, s.adm0_a3; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; +---- cdb_geocode_admin1_polygon(admin1_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin1_polygon(username text, orgname text, admin1_name text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'admin1_name': admin1_name} + + with metrics('cdb_geocode_admin1_polygon', user_geocoder_config, logger, params): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1)) AS mypolygon", ["text"]) + rv = plpy.execute(plan, [admin1_name], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode admin1 polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode admin1 polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +---- cdb_geocode_admin1_polygon(admin1_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin1_polygon(username text, orgname text, admin1_name text, country_name text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + with metrics('cdb_geocode_admin1_polygon', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1), trim($2)) AS mypolygon", ["text", "text"]) + rv = plpy.execute(plan, [admin1_name, country_name], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode admin1 polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode admin1 polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension + +---- cdb_geocode_admin1_polygon(admin1_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_admin1_polygon(admin1_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT q, ( + SELECT the_geom + FROM global_province_polygons + WHERE d.c = ANY (synonyms) + ORDER BY frequency DESC LIMIT 1 + ) geom + FROM ( + SELECT + trim(replace(lower(admin1_name),'.',' ')) c, admin1_name q + ) d + ) v; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +---- cdb_geocode_admin1_polygon(admin1_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_admin1_polygon(admin1_name text, country_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + WITH p AS (SELECT r.c, r.q, (SELECT iso3 FROM country_decoder WHERE lower(country_name) = ANY (synonyms)) i FROM (SELECT trim(replace(lower(admin1_name),'.',' ')) c, country_name q) r) + SELECT + geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_province_polygons + WHERE p.c = ANY (synonyms) + AND iso3 = p.i + ORDER BY frequency DESC LIMIT 1 + ) geom + FROM p) n; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +---- cdb_geocode_namedplace_point(city_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text) +RETURNS Geometry AS $$ + import spiexceptions + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + try: + street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3) as point;", ["text", "text", "text"]) + return plpy.execute(street_point, [username, orgname, city_name])[0]['point'] + except spiexceptions.ExternalRoutineException as e: + import sys + logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname}) + internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3) as point;", ["text", "text", "text"]) + return plpy.execute(internal_plan, [username, orgname, city_name])[0]['point'] +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +---- cdb_geocode_namedplace_point(city_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, country_name text) +RETURNS Geometry AS $$ + import spiexceptions + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + try: + street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, NULL, $4) as point;", ["text", "text", "text", "text"]) + return plpy.execute(street_point, [username, orgname, city_name, country_name])[0]['point'] + except spiexceptions.ExternalRoutineException as e: + import sys + logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname}) + internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, NULL, $4) as point;", ["text", "text", "text", "text"]) + return plpy.execute(internal_plan, [username, orgname, city_name, country_name])[0]['point'] +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +---- cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, admin1_name text, country_name text) +RETURNS Geometry AS $$ + import spiexceptions + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + try: + street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, $4, $5) as point;", ["text", "text", "text", "text", "text"]) + return plpy.execute(street_point, [username, orgname, city_name, admin1_name, country_name])[0]['point'] + except spiexceptions.ExternalRoutineException as e: + import sys + logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname}) + internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, $4, $5) as point;", ["text", "text", "text", "text", "text"]) + return plpy.execute(internal_plan, [username, orgname, city_name, admin1_name, country_name])[0]['point'] +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_internal_geocode_namedplace(username text, orgname text, city_name text, admin1_name text DEFAULT NULL, country_name text DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig, metrics + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'city_name': city_name, 'admin1_name': admin1_name, 'country_name': country_name} + + with metrics('cdb_geocode_namedplace_point', user_geocoder_config, logger, params): + try: + if admin1_name and country_name: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2), trim($3)) AS mypoint", ["text", "text", "text"]) + rv = plpy.execute(plan, [city_name, admin1_name, country_name], 1) + elif country_name: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2)) AS mypoint", ["text", "text"]) + rv = plpy.execute(plan, [city_name, country_name], 1) + else: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1)) AS mypoint", ["text"]) + rv = plpy.execute(plan, [city_name], 1) + result = rv[0]["mypoint"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode namedplace point', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode namedplace point') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension + +---- cdb_geocode_namedplace_point(city_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_namedplace_point(city_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + WITH best AS (SELECT s AS q, (SELECT the_geom FROM global_cities_points_limited gp WHERE gp.lowername = lower(p.s) ORDER BY population DESC LIMIT 1) AS geom FROM (SELECT city_name as s) p), + next AS (SELECT p.s AS q, (SELECT gp.the_geom FROM global_cities_points_limited gp, global_cities_alternates_limited ga WHERE lower(p.s) = ga.lowername AND ga.geoname_id = gp.geoname_id ORDER BY preferred DESC LIMIT 1) geom FROM (SELECT city_name as s) p WHERE p.s NOT IN (SELECT q FROM best WHERE geom IS NOT NULL)) + SELECT q, geom, TRUE AS success FROM best WHERE geom IS NOT NULL + UNION ALL + SELECT q, geom, CASE WHEN geom IS NULL THEN FALSE ELSE TRUE END AS success FROM next + ) v; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +---- cdb_geocode_namedplace_point(city_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_namedplace_point(city_name text, country_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + WITH p AS (SELECT r.s, r.c, (SELECT iso2 FROM country_decoder WHERE lower(r.c) = ANY (synonyms)) i FROM (SELECT city_name AS s, country_name::text AS c) r), + best AS (SELECT p.s AS q, p.c AS c, (SELECT gp.the_geom AS geom FROM global_cities_points_limited gp WHERE gp.lowername = lower(p.s) AND gp.iso2 = p.i ORDER BY population DESC LIMIT 1) AS geom FROM p), + next AS (SELECT p.s AS q, p.c AS c, (SELECT gp.the_geom FROM global_cities_points_limited gp, global_cities_alternates_limited ga WHERE lower(p.s) = ga.lowername AND gp.iso2 = p.i AND ga.geoname_id = gp.geoname_id ORDER BY preferred DESC LIMIT 1) geom FROM p WHERE p.s NOT IN (SELECT q FROM best WHERE c = p.c AND geom IS NOT NULL)) + SELECT geom FROM best WHERE geom IS NOT NULL + UNION ALL + SELECT geom FROM next + ) v; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +---- cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + WITH inputcountry AS ( + SELECT iso2 as isoTwo FROM country_decoder WHERE lower(country_name) = ANY (synonyms) LIMIT 1 + ), + p AS ( + SELECT r.s, r.a1, (SELECT admin1 FROM admin1_decoder, inputcountry WHERE lower(r.a1) = ANY (synonyms) AND admin1_decoder.iso2 = inputcountry.isoTwo LIMIT 1) i FROM (SELECT city_name AS s, admin1_name::text AS a1) r), + best AS (SELECT p.s AS q, p.a1 as a1, (SELECT gp.the_geom AS geom FROM global_cities_points_limited gp WHERE gp.lowername = lower(p.s) AND gp.admin1 = p.i ORDER BY population DESC LIMIT 1) AS geom FROM p), + next AS (SELECT p.s AS q, p.a1 AS a1, (SELECT gp.the_geom FROM global_cities_points_limited gp, global_cities_alternates_limited ga WHERE lower(p.s) = ga.lowername AND ga.admin1 = p.i AND ga.geoname_id = gp.geoname_id ORDER BY preferred DESC LIMIT 1) geom FROM p WHERE p.s NOT IN (SELECT q FROM best WHERE geom IS NOT NULL)) + SELECT geom FROM best WHERE geom IS NOT NULL + UNION ALL + SELECT geom FROM next + ) v; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'code': code} + + with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger, params): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1)) AS mypoint", ["text"]) + rv = plpy.execute(plan, [code], 1) + result = rv[0]["mypoint"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code point') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code double precision) +RETURNS Geometry AS $$ + SELECT cdb_dataservices_server.cdb_geocode_postalcode_point(username, orgname, code::text); +$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code text, country text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1), trim($2)) AS mypoint", ["TEXT", "TEXT"]) + rv = plpy.execute(plan, [code, country], 1) + result = rv[0]["mypoint"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code point') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code double precision, country text) +RETURNS Geometry AS $$ + SELECT cdb_dataservices_server.cdb_geocode_postalcode_point(username, orgname, code::text, country); +$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1)) AS mypolygon", ["text"]) + rv = plpy.execute(plan, [code], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code double precision) +RETURNS Geometry AS $$ + SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon(username, orgname, code::text) +$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; + + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code text, country text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1), trim($2)) AS mypolygon", ["TEXT", "TEXT"]) + rv = plpy.execute(plan, [code, country], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code double precision, country text) +RETURNS Geometry AS $$ + SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon(username, orgname, code::text, country); +$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_point(code text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_postal_code_points + WHERE postal_code = upper(d.q) + LIMIT 1 + ) geom + FROM (SELECT code q) d + ) v; + + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_point(code text, country text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_postal_code_points + WHERE postal_code = upper(d.q) + AND iso3 = ( + SELECT iso3 FROM country_decoder WHERE + lower(country) = ANY (synonyms) LIMIT 1 + ) + LIMIT 1 + ) geom + FROM (SELECT code q) d + ) v; + + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_polygon(code text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_postal_code_polygons + WHERE postal_code = upper(d.q) + LIMIT 1 + ) geom + FROM (SELECT code q) d + ) v; + + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_polygon(code text, country text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_postal_code_polygons + WHERE postal_code = upper(d.q) + AND iso3 = ( + SELECT iso3 FROM country_decoder WHERE + lower(country) = ANY (synonyms) LIMIT 1 + ) + LIMIT 1 + ) geom + FROM (SELECT code q) d + ) v; + + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_ipaddress_point(username text, orgname text, ip text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'ip': ip} + + with metrics('cdb_geocode_ipaddress_point', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_ipaddress_point(trim($1)) AS mypoint", ["TEXT"]) + rv = plpy.execute(plan, [ip], 1) + result = rv[0]["mypoint"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_ipaddress_point(ip text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + + new_ip INET; + BEGIN + BEGIN + IF family(ip::inet) = 6 THEN + new_ip := ip::inet; + ELSE + new_ip := ('::ffff:' || ip)::inet; + END IF; + EXCEPTION WHEN OTHERS THEN + SELECT NULL as geom INTO ret; + RETURN ret; + END; + + WITH + ips AS (SELECT ip s, new_ip net), + matches AS (SELECT s, (SELECT the_geom FROM ip_address_locations WHERE network_start_ip <= ips.net ORDER BY network_start_ip DESC LIMIT 1) geom FROM ips) + SELECT geom INTO ret + FROM matches; + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; +CREATE TYPE cdb_dataservices_server.isoline AS (center geometry(Geometry,4326), data_range integer, the_geom geometry(Multipolygon,4326)); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_routing_isolines(username TEXT, orgname TEXT, type TEXT, source geometry(Geometry, 4326), mode TEXT, data_range integer[], options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + import json + from cartodb_services.here import HereMapsRoutingIsoline + from cartodb_services.metrics import QuotaService + from cartodb_services.here.types import geo_polyline_to_multipolygon + from cartodb_services.tools import Logger,LoggerConfig + + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + # -- Check the quota + quota_service = QuotaService(user_isolines_routing_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + try: + client = HereMapsRoutingIsoline(user_isolines_routing_config.heremaps_app_id, + user_isolines_routing_config.heremaps_app_code, logger) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + source_str = 'geo!%f,%f' % (lat, lon) + else: + source_str = None + + if type == 'isodistance': + resp = client.calculate_isodistance(source_str, mode, data_range, options) + elif type == 'isochrone': + resp = client.calculate_isochrone(source_str, mode, data_range, options) + + if resp: + result = [] + for isoline in resp: + data_range_n = isoline['range'] + polyline = isoline['geom'] + multipolygon = geo_polyline_to_multipolygon(polyline) + result.append([source, data_range_n, multipolygon]) + quota_service.increment_success_service_use() + quota_service.increment_isolines_service_use(len(resp)) + return result + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get mapzen isolines') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + import json + from cartodb_services.mapzen import MatrixClient, MapzenIsolines + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_isolines_routing_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + try: + client = MatrixClient(user_isolines_routing_config.mapzen_matrix_api_key, logger, user_isolines_routing_config.mapzen_matrix_service_params) + mapzen_isolines = MapzenIsolines(client, logger) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = {'lat': lat, 'lon': lon} + else: + raise Exception('source is NULL') + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapzen_isolines.calculate_isodistance(origin, mode, r) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l['lon'], l['lat']) for l in locations]) + sql = "SELECT ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + quota_service.increment_success_service_use() + quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get mapzen isolines') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + mapbox_isolines = MapboxIsolines(client, service_manager.logger) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapbox_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxTrueIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapbox_iso_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox true isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox true isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.tomtom import TomTomIsolines + from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_TOMTOM.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = tomtom_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get TomTom isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get TomTom isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + import json + from cartodb_services.mapzen import MatrixClient, MapzenIsochrones + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + from cartodb_services.mapzen.types import coordinates_to_polygon + + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + # -- Check the quota + quota_service = QuotaService(user_isolines_routing_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + try: + mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key, + logger, user_isolines_routing_config.mapzen_isochrones_service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = {'lat': lat, 'lon': lon} + else: + raise Exception('source is NULL') + + resp = mapzen_isochrones.isochrone(origin, mode, data_range) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + quota_service.increment_success_service_use() + quota_service.increment_isolines_service_use(len(result)) + return result + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to get mapzen isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get mapzen isochrones') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + mapbox_isolines = MapboxIsolines(client, service_manager.logger) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxTrueIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + resp = mapbox_iso_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox true isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox true isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.tomtom import TomTomIsolines + from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_TOMTOM.get(mode) + + resp = tomtom_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get TomTom isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get TomTom isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + if user_isolines_config.google_services_user: + raise Exception('This service is not available for google service users.') + + params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + + with metrics('cdb_isodistance', user_isolines_config, logger, params): + if user_isolines_config.heremaps_provider: + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_iso_provider: + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + else: + raise Exception('Requested isolines provider is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- heremaps isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_here_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + type = 'isodistance' + + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(here_plan, [username, orgname, type, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapzen isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapbox isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapbox true isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- tomtom isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + if user_isolines_config.google_services_user: + raise Exception('This service is not available for google service users.') + + params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + + with metrics('cdb_isochrone', user_isolines_config, logger, params): + if user_isolines_config.heremaps_provider: + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_iso_provider: + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + else: + raise Exception('Requested isolines provider is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- heremaps isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_here_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + type = 'isochrone' + + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(here_plan, [username, orgname, type, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapzen isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapbox isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapbox true isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- tomtom isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +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$$; diff --git a/server/extension/cdb_dataservices_server.control b/server/extension/cdb_dataservices_server.control index 8030c1d..9788bda 100644 --- a/server/extension/cdb_dataservices_server.control +++ b/server/extension/cdb_dataservices_server.control @@ -1,5 +1,5 @@ comment = 'CartoDB dataservices server extension' -default_version = '0.36.0' +default_version = '0.37.0' requires = 'plpythonu, plproxy, postgis, cdb_geocoder' superuser = true schema = cdb_dataservices_server diff --git a/server/extension/cdb_dataservices_server--0.35.1--0.36.0.sql b/server/extension/old_versions/cdb_dataservices_server--0.35.1--0.36.0.sql similarity index 100% rename from server/extension/cdb_dataservices_server--0.35.1--0.36.0.sql rename to server/extension/old_versions/cdb_dataservices_server--0.35.1--0.36.0.sql diff --git a/server/extension/cdb_dataservices_server--0.36.0--0.35.1.sql b/server/extension/old_versions/cdb_dataservices_server--0.36.0--0.35.1.sql similarity index 100% rename from server/extension/cdb_dataservices_server--0.36.0--0.35.1.sql rename to server/extension/old_versions/cdb_dataservices_server--0.36.0--0.35.1.sql diff --git a/server/extension/cdb_dataservices_server--0.36.0.sql b/server/extension/old_versions/cdb_dataservices_server--0.36.0.sql similarity index 100% rename from server/extension/cdb_dataservices_server--0.36.0.sql rename to server/extension/old_versions/cdb_dataservices_server--0.36.0.sql diff --git a/server/extension/test/expected/00_install_test.out b/server/extension/test/expected/00_install_test.out index 6132b3b..53431a7 100644 --- a/server/extension/test/expected/00_install_test.out +++ b/server/extension/test/expected/00_install_test.out @@ -39,6 +39,12 @@ SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routi (1 row) +SELECT cartodb.cdb_conf_setconf('mapbox_iso_conf', '{"isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); + cdb_conf_setconf +------------------ + +(1 row) + SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); cdb_conf_setconf ------------------ diff --git a/server/extension/test/sql/00_install_test.sql b/server/extension/test/sql/00_install_test.sql index 3beedfd..c291021 100644 --- a/server/extension/test/sql/00_install_test.sql +++ b/server/extension/test/sql/00_install_test.sql @@ -16,6 +16,7 @@ SELECT cartodb.cdb_conf_setconf('redis_metadata_config', '{"redis_host": "localh SELECT cartodb.cdb_conf_setconf('heremaps_conf', '{"geocoder": {"app_id": "dummy_id", "app_code": "dummy_code", "geocoder_cost_per_hit": 1}, "isolines": {"app_id": "dummy_id", "app_code": "dummy_code"}}'); SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"routing": {"api_key": "routing_dummy_api_key", "monthly_quota": 1500000}, "geocoder": {"api_key": "geocoder_dummy_api_key", "monthly_quota": 1500000}, "matrix": {"api_key": "matrix_dummy_api_key", "monthly_quota": 1500000}}'); SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); +SELECT cartodb.cdb_conf_setconf('mapbox_iso_conf', '{"isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); SELECT cartodb.cdb_conf_setconf('geocodio_conf', '{"geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}}'); SELECT cartodb.cdb_conf_setconf('logger_conf', '{"geocoder_log_path": "/dev/null"}'); From 8c3b10a061f4e2c11d60ec00d8f0212179b6af15 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Fri, 7 Feb 2020 16:24:04 +0100 Subject: [PATCH 05/20] Client extension changes --- ...db_dataservices_client--0.28.0--0.29.0.sql | 161 + ...db_dataservices_client--0.29.0--0.28.0.sql | 20 + client/cdb_dataservices_client--0.29.0.sql | 5983 +++++++++++++++++ client/cdb_dataservices_client.control | 2 +- ...db_dataservices_client--0.27.0--0.28.0.sql | 0 ...db_dataservices_client--0.28.0--0.27.0.sql | 0 .../cdb_dataservices_client--0.28.0.sql | 0 7 files changed, 6165 insertions(+), 1 deletion(-) create mode 100644 client/cdb_dataservices_client--0.28.0--0.29.0.sql create mode 100644 client/cdb_dataservices_client--0.29.0--0.28.0.sql create mode 100644 client/cdb_dataservices_client--0.29.0.sql rename client/{ => old_versions}/cdb_dataservices_client--0.27.0--0.28.0.sql (100%) rename client/{ => old_versions}/cdb_dataservices_client--0.28.0--0.27.0.sql (100%) rename client/{ => old_versions}/cdb_dataservices_client--0.28.0.sql (100%) diff --git a/client/cdb_dataservices_client--0.28.0--0.29.0.sql b/client/cdb_dataservices_client--0.28.0--0.29.0.sql new file mode 100644 index 0000000..4808b5c --- /dev/null +++ b/client/cdb_dataservices_client--0.28.0--0.29.0.sql @@ -0,0 +1,161 @@ +--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES +-- Complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.29.0'" to load this file. \quit + +-- Make sure we have a sane search path to create/update the extension +SET search_path = "$user",cartodb,public,cdb_dataservices_client; + +-- HERE goes your code to upgrade/downgrade + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isochrone(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isodistance(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isochrone(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isodistance(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; + + +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + + +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; diff --git a/client/cdb_dataservices_client--0.29.0--0.28.0.sql b/client/cdb_dataservices_client--0.29.0--0.28.0.sql new file mode 100644 index 0000000..8e742d8 --- /dev/null +++ b/client/cdb_dataservices_client--0.29.0--0.28.0.sql @@ -0,0 +1,20 @@ +--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES +-- Complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.28.0'" to load this file. \quit + +-- Make sure we have a sane search path to create/update the extension +SET search_path = "$user",cartodb,public,cdb_dataservices_client; + +-- HERE goes your code to upgrade/downgrade + +DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_mapbox_iso_isochrone; + +DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_mapbox_iso_isodistance; + +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe; + +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe; + +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isochrone; + +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isodistance; diff --git a/client/cdb_dataservices_client--0.29.0.sql b/client/cdb_dataservices_client--0.29.0.sql new file mode 100644 index 0000000..14a6cf4 --- /dev/null +++ b/client/cdb_dataservices_client--0.29.0.sql @@ -0,0 +1,5983 @@ +--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 + +-- Make sure we have a sane search path to create/update the extension +SET search_path = "$user",cartodb,public,cdb_dataservices_client; +-- Taken from https://wiki.postgresql.org/wiki/Count_estimate +CREATE FUNCTION cdb_dataservices_client.cdb_count_estimate(query text) RETURNS INTEGER AS +$func$ +DECLARE + rec record; + ROWS INTEGER; +BEGIN + FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP + ROWS := SUBSTRING(rec."QUERY PLAN" FROM ' rows=([[:digit:]]+)'); + EXIT WHEN ROWS IS NOT NULL; + END LOOP; + + RETURN ROWS; +END +$func$ LANGUAGE plpgsql; + +-- Taken from https://stackoverflow.com/a/48013356/351721 +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_jsonb_array_casttext(jsonb) RETURNS text[] AS $f$ + SELECT array_agg(x) || ARRAY[]::text[] FROM jsonb_array_elements_text($1) t(x); +$f$ LANGUAGE sql IMMUTABLE;-- +-- 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' STABLE PARALLEL SAFE; +CREATE TYPE cdb_dataservices_client._entity_config AS ( + username text, + organization_name text, + apikey_permissions json +); + +-- +-- 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; + apikey_config json; + is_organization boolean; + organization_name text DEFAULT NULL; +BEGIN + SELECT cartodb.cdb_conf_getconf('api_keys_'||session_user) INTO apikey_config; + + 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 cartodb.cdb_conf_getconf('user_config')->>'entity_name' INTO organization_name; + END IF; + result.username = apikey_config->>'username'; + result.organization_name = organization_name; + result.apikey_permissions = apikey_config->'permissions'; + RETURN result; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL SAFE + SET search_path = pg_temp; + +CREATE TYPE cdb_dataservices_client.isoline AS ( + center geometry(Geometry,4326), + data_range integer, + the_geom geometry(Multipolygon,4326) +); + +CREATE TYPE cdb_dataservices_client.geocoding AS ( + cartodb_id integer, + the_geom geometry(Point,4326), + metadata jsonb +); + +CREATE TYPE cdb_dataservices_client.simple_route AS ( + shape geometry(LineString,4326), + length real, + duration integer +); + +-- For the OBS_Meta functions +CREATE TYPE cdb_dataservices_client.obs_meta_numerator AS (numer_id text, numer_name text, numer_description text, numer_weight text, numer_license text, numer_source text, numer_type text, numer_aggregate text, numer_extra jsonb, numer_tags jsonb, valid_denom boolean, valid_geom boolean, valid_timespan boolean); + +CREATE TYPE cdb_dataservices_client.obs_meta_denominator AS (denom_id text, denom_name text, denom_description text, denom_weight text, denom_license text, denom_source text, denom_type text, denom_aggregate text, denom_extra jsonb, denom_tags jsonb, valid_numer boolean, valid_geom boolean, valid_timespan boolean); + +CREATE TYPE cdb_dataservices_client.obs_meta_geometry AS (geom_id text, geom_name text, geom_description text, geom_weight text, geom_aggregate text, geom_license text, geom_source text, valid_numer boolean, valid_denom boolean, valid_timespan boolean, score numeric, numtiles bigint, notnull_percent numeric, numgeoms numeric, percentfill numeric, estnumgeoms numeric, meanmediansize numeric, geom_type text, geom_extra jsonb, geom_tags jsonb); + +CREATE TYPE cdb_dataservices_client.obs_meta_timespan AS (timespan_id text, timespan_name text, timespan_description text, timespan_weight text, timespan_aggregate text, timespan_license text, timespan_source text, valid_numer boolean, valid_denom boolean, valid_geom boolean, timespan_type text, timespan_extra jsonb, timespan_tags jsonb); + + +-- For quotas and services configuration +CREATE TYPE cdb_dataservices_client.service_type AS ENUM ( + 'isolines', + 'hires_geocoder', + 'routing', + 'observatory' +); + +CREATE TYPE cdb_dataservices_client.service_quota_info AS ( + service cdb_dataservices_client.service_type, + monthly_quota NUMERIC, + used_quota NUMERIC, + soft_limit BOOLEAN, + provider TEXT +); + +CREATE TYPE cdb_dataservices_client.service_quota_info_batch AS ( + service cdb_dataservices_client.service_type, + monthly_quota NUMERIC, + used_quota NUMERIC, + soft_limit BOOLEAN, + provider TEXT, + max_batch_size NUMERIC +); +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_admin0_polygon (country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_admin0_polygon(username, orgname, country_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_admin1_polygon (admin1_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_admin1_polygon (admin1_name text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name, country_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point (city_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point (city_name text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, country_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point (city_name text ,admin1_name text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, admin1_name, country_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_polygon (postal_code text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_polygon (postal_code double precision ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_point (postal_code text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_point (postal_code double precision ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_ipaddress_point (ip_address text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_ipaddress_point(username, orgname, ip_address) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point (searches jsonb) +RETURNS SETOF cdb_dataservices_client.geocoding AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client.__cdb_bulk_geocode_street_point(username, orgname, searches); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_here_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_here_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_google_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_google_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_mapbox_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_tomtom_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocodio_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_geocodio_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapzen_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._cdb_mapzen_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_isodistance(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_isochrone(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_isochrone(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isochrone(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isochrone(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapzen_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapzen_isochrone(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_isodistance(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isodistance(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isodistance(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapzen_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapzen_isodistance(username, orgname, source, mode, range, options); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_route_point_to_point (origin public.geometry(Point, 4326) ,destination public.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; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'routing' THEN + RAISE EXCEPTION 'Routing permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT * 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 STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_route_with_waypoints (waypoints public.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; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'routing' THEN + RAISE EXCEPTION 'Routing permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT * FROM cdb_dataservices_client._cdb_route_with_waypoints(username, orgname, waypoints, mode, options, units) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_get_demographic_snapshot (geom public.geometry(Geometry, 4326) ,time_span text DEFAULT '2009 - 2013'::text ,geometry_level text DEFAULT NULL) +RETURNS json AS $$ +DECLARE + ret json; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_get_demographic_snapshot(username, orgname, geom, time_span, geometry_level) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_get_segment_snapshot (geom public.geometry(Geometry, 4326) ,geometry_level text DEFAULT NULL) +RETURNS json AS $$ +DECLARE + ret json; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_get_segment_snapshot(username, orgname, geom, geometry_level) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdemographicsnapshot (geom public.geometry(Geometry, 4326) ,time_span text DEFAULT NULL ,geometry_level text DEFAULT NULL) +RETURNS SETOF JSON AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdemographicsnapshot(username, orgname, geom, time_span, geometry_level); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getsegmentsnapshot (geom public.geometry(Geometry, 4326) ,geometry_level text DEFAULT NULL) +RETURNS SETOF JSON AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getsegmentsnapshot(username, orgname, geom, geometry_level); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundary (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getboundary(username, orgname, geom, boundary_id, time_span) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundaryid (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL) +RETURNS text AS $$ +DECLARE + ret text; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getboundaryid(username, orgname, geom, boundary_id, time_span) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundarybyid (geometry_id text ,boundary_id text ,time_span text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getboundarybyid(username, orgname, geometry_id, boundary_id, time_span) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundariesbygeometry (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getboundariesbygeometry(username, orgname, geom, boundary_id, time_span, overlap_type); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundariesbypointandradius (geom public.geometry(Geometry, 4326) ,radius numeric ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getboundariesbypointandradius(username, orgname, geom, radius, boundary_id, time_span, overlap_type); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getpointsbygeometry (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getpointsbygeometry(username, orgname, geom, boundary_id, time_span, overlap_type); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getpointsbypointandradius (geom public.geometry(Geometry, 4326) ,radius numeric ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getpointsbypointandradius(username, orgname, geom, radius, boundary_id, time_span, overlap_type); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getmeasure (geom public.Geometry ,measure_id text ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS numeric AS $$ +DECLARE + ret numeric; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getmeasure(username, orgname, geom, measure_id, normalize, boundary_id, time_span) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getmeasurebyid (geom_ref text ,measure_id text ,boundary_id text ,time_span text DEFAULT NULL) +RETURNS numeric AS $$ +DECLARE + ret numeric; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getmeasurebyid(username, orgname, geom_ref, measure_id, boundary_id, time_span) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdata (geomvals geomval[] ,params json ,merge boolean DEFAULT true) +RETURNS TABLE(id int, data json) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomvals, params, merge); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdata (geomrefs text[] ,params json) +RETURNS TABLE(id text, data json) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomrefs, params); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getmeta (geom_ref public.Geometry(Geometry, 4326) ,params json ,max_timespan_rank integer DEFAULT NULL ,max_score_rank integer DEFAULT NULL ,target_geoms integer DEFAULT NULL) +RETURNS json AS $$ +DECLARE + ret json; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_metadatavalidation (geom_extent public.Geometry(Geometry, 4326) ,geom_type text ,params json ,target_geoms integer DEFAULT NULL) +RETURNS TABLE(valid boolean, errors text[]) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_metadatavalidation(username, orgname, geom_extent, geom_type, params, target_geoms); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getcategory (geom public.Geometry ,category_id text ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS text AS $$ +DECLARE + ret text; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getcategory(username, orgname, geom, category_id, boundary_id, time_span) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getuscensusmeasure (geom public.Geometry ,name text ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS numeric AS $$ +DECLARE + ret numeric; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getuscensusmeasure(username, orgname, geom, name, normalize, boundary_id, time_span) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getuscensuscategory (geom public.Geometry ,name text ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS text AS $$ +DECLARE + ret text; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getuscensuscategory(username, orgname, geom, name, boundary_id, time_span) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getpopulation (geom public.Geometry ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS numeric AS $$ +DECLARE + ret numeric; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_getpopulation(username, orgname, geom, normalize, boundary_id, time_span) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_search (search_term text ,relevant_boundary text DEFAULT NULL) +RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_search(username, orgname, search_term, relevant_boundary); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailableboundaries (geom public.Geometry ,timespan text DEFAULT NULL) +RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailableboundaries(username, orgname, geom, timespan); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_dumpversion () +RETURNS text AS $$ +DECLARE + ret text; + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT cdb_dataservices_client._obs_dumpversion(username, orgname) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailablenumerators (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,denom_id text DEFAULT NULL ,geom_id text DEFAULT NULL ,timespan text DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailablenumerators(username, orgname, bounds, filter_tags, denom_id, geom_id, timespan); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getnumerators (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,section_tags text[] DEFAULT ARRAY[]::TEXT[] ,subsection_tags text[] DEFAULT ARRAY[]::TEXT[] ,other_tags text[] DEFAULT ARRAY[]::TEXT[] ,ids text[] DEFAULT ARRAY[]::TEXT[] ,name text DEFAULT NULL ,denom_id text DEFAULT '' ,geom_id text DEFAULT '' ,timespan text DEFAULT '') +RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client.__obs_getnumerators(username, orgname, bounds, section_tags, subsection_tags, other_tags, ids, name, denom_id, geom_id, timespan); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailabledenominators (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,geom_id text DEFAULT NULL ,timespan text DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_denominator AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailabledenominators(username, orgname, bounds, filter_tags, numer_id, geom_id, timespan); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailablegeometries (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,denom_id text DEFAULT NULL ,timespan text DEFAULT NULL ,number_geometries integer DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_geometry AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailablegeometries(username, orgname, bounds, filter_tags, numer_id, denom_id, timespan, number_geometries); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailabletimespans (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,denom_id text DEFAULT NULL ,geom_id text DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_timespan AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailabletimespans(username, orgname, bounds, filter_tags, numer_id, denom_id, geom_id); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_legacybuildermetadata (aggregate_type text DEFAULT NULL) +RETURNS TABLE(name text, subsection json) AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_legacybuildermetadata(username, orgname, aggregate_type); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_quota_info () +RETURNS SETOF service_quota_info AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_service_quota_info(username, orgname); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch () +RETURNS SETOF service_quota_info_batch AS $$ +DECLARE + + username text; + orgname text; + apikey_permissions json; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_service_quota_info_batch(username, orgname); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC) +RETURNS BOOLEAN AS $$ +DECLARE + ret BOOLEAN; + username text; + orgname text; + apikey_permissions json; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + + + -- 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_enough_quota(username, orgname, service, input_size) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_get_rate_limit (service text) +RETURNS json AS $$ +DECLARE + ret json; + username text; + orgname text; + apikey_permissions json; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + + + -- 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_service_get_rate_limit(username, orgname, service) INTO ret; RETURN ret; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_set_user_rate_limit (username text ,orgname text ,service text ,rate_limit json) +RETURNS void AS $$ +DECLARE + + + +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, p json); + -- 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; + + PERFORM cdb_dataservices_client._cdb_service_set_user_rate_limit(username, orgname, service, rate_limit); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_set_org_rate_limit (username text ,orgname text ,service text ,rate_limit json) +RETURNS void AS $$ +DECLARE + + + +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, p json); + -- 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; + + PERFORM cdb_dataservices_client._cdb_service_set_org_rate_limit(username, orgname, service, rate_limit); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Public dataservices API function +-- +-- These are the only ones with permissions to publicuser role +-- and should also be the only ones with SECURITY DEFINER + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_set_server_rate_limit (username text ,orgname text ,service text ,rate_limit json) +RETURNS void AS $$ +DECLARE + + + +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, p json); + -- 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; + + PERFORM cdb_dataservices_client._cdb_service_set_server_rate_limit(username, orgname, service, rate_limit); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +CREATE TYPE cdb_dataservices_client.ds_fdw_metadata as (schemaname text, tabname text, servername text); +CREATE TYPE cdb_dataservices_client.ds_return_metadata as (colnames text[], coltypes text[]); + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_PrepareTableOBS_GetMeasure( + output_table_name text, + params json +) RETURNS boolean AS $$ +DECLARE + username text; + user_db_role text; + orgname text; + user_schema text; + result boolean; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + + SELECT session_user INTO user_db_role; + + SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument'; + END IF; + + IF orgname IS NULL OR orgname = '' OR orgname = '""' THEN + user_schema := 'public'; + ELSE + user_schema := username; + END IF; + + SELECT cdb_dataservices_client.__DST_PrepareTableOBS_GetMeasure( + username, + orgname, + user_db_role, + user_schema, + output_table_name, + params + ) INTO result; + + RETURN result; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE + SET search_path = pg_temp; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_PopulateTableOBS_GetMeasure( + table_name text, + output_table_name text, + params json +) RETURNS boolean AS $$ +DECLARE + username text; + user_db_role text; + orgname text; + dbname text; + user_schema text; + result boolean; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + + SELECT session_user INTO user_db_role; + + SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument'; + END IF; + + IF orgname IS NULL OR orgname = '' OR orgname = '""' THEN + user_schema := 'public'; + ELSE + user_schema := username; + END IF; + + SELECT current_database() INTO dbname; + + SELECT cdb_dataservices_client.__DST_PopulateTableOBS_GetMeasure( + username, + orgname, + user_db_role, + user_schema, + dbname, + table_name, + output_table_name, + params + ) INTO result; + + RETURN result; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE + SET search_path = pg_temp; + + + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.__DST_PrepareTableOBS_GetMeasure( + username text, + orgname text, + user_db_role text, + user_schema text, + output_table_name text, + params json +) RETURNS boolean AS $$ + function_name = 'OBS_GetMeasure' + # Obtain return types for augmentation procedure + ds_return_metadata = plpy.execute("SELECT colnames, coltypes " + "FROM cdb_dataservices_client._DST_GetReturnMetadata({username}::text, {orgname}::text, {function_name}::text, {params}::json);" + .format( + username=plpy.quote_nullable(username), + orgname=plpy.quote_nullable(orgname), + function_name=plpy.quote_literal(function_name), + params=plpy.quote_literal(params) + ) + ) + if ds_return_metadata[0]["colnames"]: + colnames_arr = ds_return_metadata[0]["colnames"] + coltypes_arr = ds_return_metadata[0]["coltypes"] + else: + raise Exception('Error retrieving OBS_GetMeasure metadata') + + + # Prepare column and type strings required in the SQL queries + columns_with_types_arr = [colnames_arr[i] + ' ' + coltypes_arr[i] for i in range(0,len(colnames_arr))] + columns_with_types = ','.join(columns_with_types_arr) + + # Create a new table with the required columns + plpy.execute('CREATE TABLE "{schema}".{table_name} ( ' + 'cartodb_id int, the_geom public.geometry, {columns_with_types} ' + ');' + .format(schema=user_schema, table_name=output_table_name, columns_with_types=columns_with_types) + ) + + plpy.execute('ALTER TABLE "{schema}".{table_name} OWNER TO "{user}";' + .format(schema=user_schema, table_name=output_table_name, user=user_db_role) + ) + + return True +$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.__DST_PopulateTableOBS_GetMeasure( + username text, + orgname text, + user_db_role text, + user_schema text, + dbname text, + table_name text, + output_table_name text, + params json +) RETURNS boolean AS $$ + function_name = 'OBS_GetMeasure' + # Obtain return types for augmentation procedure + ds_return_metadata = plpy.execute( + "SELECT colnames, coltypes " + "FROM cdb_dataservices_client._DST_GetReturnMetadata({username}::text, {orgname}::text, {function_name}::text, {params}::json);" .format( + username=plpy.quote_nullable(username), + orgname=plpy.quote_nullable(orgname), + function_name=plpy.quote_literal(function_name), + params=plpy.quote_literal(params))) + + if ds_return_metadata[0]["colnames"]: + colnames_arr = ds_return_metadata[0]["colnames"] + coltypes_arr = ds_return_metadata[0]["coltypes"] + else: + raise Exception('Error retrieving OBS_GetMeasure metadata') + + # Prepare column and type strings required in the SQL queries + columns_with_types_arr = [ + colnames_arr[i] + + ' ' + + coltypes_arr[i] for i in range( + 0, + len(colnames_arr))] + columns_with_types = ','.join(columns_with_types_arr) + aliased_colname_list = ','.join( + ['result.' + name for name in colnames_arr]) + + # Instruct the OBS server side to establish a FDW + # The metadata is obtained as well in order to: + # - (a) be able to write the query to grab the actual data to be executed in the remote server via pl/proxy, + # - (b) be able to tell OBS to free resources when done. + ds_fdw_metadata = plpy.execute( + "SELECT schemaname, tabname, servername " + "FROM cdb_dataservices_client._DST_ConnectUserTable({username}::text, {orgname}::text, {user_db_role}::text, " + "{schema}::text, {dbname}::text, {table_name}::text);" .format( + username=plpy.quote_nullable(username), + orgname=plpy.quote_nullable(orgname), + user_db_role=plpy.quote_literal(user_db_role), + schema=plpy.quote_literal(user_schema), + dbname=plpy.quote_literal(dbname), + table_name=plpy.quote_literal(table_name))) + + if ds_fdw_metadata[0]["schemaname"]: + server_schema = ds_fdw_metadata[0]["schemaname"] + server_table_name = ds_fdw_metadata[0]["tabname"] + server_name = ds_fdw_metadata[0]["servername"] + else: + raise Exception('Error connecting dataset via FDW') + + # Create a new table with the required columns + plpy.execute( + 'INSERT INTO "{schema}".{analysis_table_name} ' + 'SELECT ut.cartodb_id, ut.the_geom, {colname_list} ' + 'FROM "{schema}".{table_name} ut ' + 'LEFT JOIN cdb_dataservices_client._DST_FetchJoinFdwTableData({username}::text, {orgname}::text, {server_schema}::text, {server_table_name}::text, ' + '{function_name}::text, {params}::json) ' + 'AS result ({columns_with_types}, cartodb_id int) ' + 'ON result.cartodb_id = ut.cartodb_id;' .format( + schema=user_schema, + analysis_table_name=output_table_name, + colname_list=aliased_colname_list, + table_name=table_name, + username=plpy.quote_nullable(username), + orgname=plpy.quote_nullable(orgname), + server_schema=plpy.quote_literal(server_schema), + server_table_name=plpy.quote_literal(server_table_name), + function_name=plpy.quote_literal(function_name), + params=plpy.quote_literal(params), + columns_with_types=columns_with_types)) + + # Wipe user FDW data from the server + wiped = plpy.execute( + "SELECT cdb_dataservices_client._DST_DisconnectUserTable({username}::text, {orgname}::text, {server_schema}::text, " + "{server_table_name}::text, {fdw_server}::text)" .format( + username=plpy.quote_nullable(username), + orgname=plpy.quote_nullable(orgname), + server_schema=plpy.quote_literal(server_schema), + server_table_name=plpy.quote_literal(server_table_name), + fdw_server=plpy.quote_literal(server_name))) + + return True +$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_ConnectUserTable( + username text, + orgname text, + user_db_role text, + user_schema text, + dbname text, + table_name text +)RETURNS cdb_dataservices_client.ds_fdw_metadata AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + TARGET cdb_dataservices_server._DST_ConnectUserTable; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_GetReturnMetadata( + username text, + orgname text, + function_name text, + params json +) RETURNS cdb_dataservices_client.ds_return_metadata AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + TARGET cdb_dataservices_server._DST_GetReturnMetadata; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_FetchJoinFdwTableData( + username text, + orgname text, + table_schema text, + table_name text, + function_name text, + params json +) RETURNS SETOF record AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + TARGET cdb_dataservices_server._DST_FetchJoinFdwTableData; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_DisconnectUserTable( + username text, + orgname text, + table_schema text, + table_name text, + server_name text +) RETURNS boolean AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + TARGET cdb_dataservices_server._DST_DisconnectUserTable; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point (query text, + street_column text, city_column text default null, state_column text default null, country_column text default null, batch_size integer DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.geocoding AS $$ +DECLARE + query_row_count integer; + enough_quota boolean; + remaining_quota integer; + max_batch_size integer; + + cartodb_id_batch integer; + batches_n integer; + DEFAULT_BATCH_SIZE CONSTANT numeric := 100; + MAX_SAFE_BATCH_SIZE CONSTANT numeric := 5000; + + temp_table_name text; + username text; + orgname text; + apikey_permissions json; +BEGIN + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + SELECT csqi.monthly_quota - csqi.used_quota AS remaining_quota, csqi.max_batch_size + INTO remaining_quota, max_batch_size + FROM cdb_dataservices_client.cdb_service_quota_info_batch() csqi + WHERE service = 'hires_geocoder'; + RAISE DEBUG 'remaining_quota: %; max_batch_size: %', remaining_quota, max_batch_size; + + IF batch_size IS NULL THEN + batch_size := max_batch_size; + ELSIF batch_size > max_batch_size THEN + RAISE EXCEPTION 'batch_size must be lower than %', max_batch_size + 1; + END IF; + + IF batch_size > MAX_SAFE_BATCH_SIZE THEN + batch_size := MAX_SAFE_BATCH_SIZE; + END IF; + + EXECUTE format('SELECT count(1), ceil(count(1)::float/%s) FROM (%s) _x', batch_size, query) + INTO query_row_count, batches_n; + + RAISE DEBUG 'cdb_bulk_geocode_street_point --> query_row_count: %; query: %; country: %; state: %; city: %; street: %', + query_row_count, query, country_column, state_column, city_column, street_column; + SELECT cdb_dataservices_client.cdb_enough_quota('hires_geocoder', query_row_count) INTO enough_quota; + IF enough_quota IS NULL OR NOT enough_quota THEN + RAISE EXCEPTION 'Remaining quota: %. Estimated cost: %', remaining_quota, query_row_count; + END IF; + + RAISE DEBUG 'batches_n: %', batches_n; + + temp_table_name := 'bulk_geocode_street_' || md5(random()::text); + + EXECUTE format('CREATE TEMPORARY TABLE %s ' || + '(cartodb_id integer, the_geom public.geometry(Point,4326), metadata jsonb)', + temp_table_name); + + select + coalesce(street_column, ''''''), coalesce(city_column, ''''''), + coalesce(state_column, ''''''), coalesce(country_column, '''''') + into street_column, city_column, state_column, country_column; + + IF batches_n > 0 THEN + FOR cartodb_id_batch in 0..(batches_n - 1) + LOOP + EXECUTE format( + 'WITH geocoding_data as (' || + ' SELECT ' || + ' json_build_object(''id'', cartodb_id, ''address'', %s, ''city'', %s, ''state'', %s, ''country'', %s) as data , ' || + ' floor((row_number() over () - 1)::float/$1) as batch' || + ' FROM (%s) _x' || + ') ' || + 'INSERT INTO %s SELECT (cdb_dataservices_client._cdb_bulk_geocode_street_point(jsonb_agg(data))).* ' || + 'FROM geocoding_data ' || + 'WHERE batch = $2', street_column, city_column, state_column, country_column, query, temp_table_name) + USING batch_size, cartodb_id_batch; + + END LOOP; + END IF; + + RETURN QUERY EXECUTE 'SELECT * FROM ' || quote_ident(temp_table_name); +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin0_polygon_exception_safe (country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_admin0_polygon(username, orgname, country_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon_exception_safe (admin1_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon_exception_safe (admin1_name text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name, country_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point_exception_safe (city_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point_exception_safe (city_name text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, country_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point_exception_safe (city_name text ,admin1_name text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, admin1_name, country_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon_exception_safe (postal_code text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon_exception_safe (postal_code double precision ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point_exception_safe (postal_code text ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point_exception_safe (postal_code double precision ,country_name text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_ipaddress_point_exception_safe (ip_address text) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_ipaddress_point(username, orgname, ip_address) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point_exception_safe (searches jsonb) +RETURNS SETOF cdb_dataservices_client.geocoding AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client.__cdb_bulk_geocode_street_point(username, orgname, searches); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_here_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_here_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_google_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_google_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_mapbox_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_tomtom_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocodio_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_geocodio_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN + RAISE EXCEPTION 'Geocoding permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_mapzen_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_isodistance(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_isochrone(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_isochrone(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isochrone(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isochrone(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapzen_isochrone(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_isodistance(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isodistance(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isodistance(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN + RAISE EXCEPTION 'Isolines permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapzen_isodistance(username, orgname, source, mode, range, options); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_point_to_point_exception_safe (origin public.geometry(Point, 4326) ,destination public.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; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'routing' THEN + RAISE EXCEPTION 'Routing permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_with_waypoints_exception_safe (waypoints public.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; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'routing' THEN + RAISE EXCEPTION 'Routing permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT * FROM cdb_dataservices_client._cdb_route_with_waypoints(username, orgname, waypoints, mode, options, units) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_get_demographic_snapshot_exception_safe (geom public.geometry(Geometry, 4326) ,time_span text DEFAULT '2009 - 2013'::text ,geometry_level text DEFAULT NULL) +RETURNS json AS $$ +DECLARE + ret json; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_get_demographic_snapshot(username, orgname, geom, time_span, geometry_level) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_get_segment_snapshot_exception_safe (geom public.geometry(Geometry, 4326) ,geometry_level text DEFAULT NULL) +RETURNS json AS $$ +DECLARE + ret json; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_get_segment_snapshot(username, orgname, geom, geometry_level) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdemographicsnapshot_exception_safe (geom public.geometry(Geometry, 4326) ,time_span text DEFAULT NULL ,geometry_level text DEFAULT NULL) +RETURNS SETOF JSON AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdemographicsnapshot(username, orgname, geom, time_span, geometry_level); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getsegmentsnapshot_exception_safe (geom public.geometry(Geometry, 4326) ,geometry_level text DEFAULT NULL) +RETURNS SETOF JSON AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getsegmentsnapshot(username, orgname, geom, geometry_level); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundary_exception_safe (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getboundary(username, orgname, geom, boundary_id, time_span) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundaryid_exception_safe (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL) +RETURNS text AS $$ +DECLARE + ret text; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getboundaryid(username, orgname, geom, boundary_id, time_span) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundarybyid_exception_safe (geometry_id text ,boundary_id text ,time_span text DEFAULT NULL) +RETURNS public.Geometry AS $$ +DECLARE + ret public.Geometry; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getboundarybyid(username, orgname, geometry_id, boundary_id, time_span) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundariesbygeometry_exception_safe (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getboundariesbygeometry(username, orgname, geom, boundary_id, time_span, overlap_type); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundariesbypointandradius_exception_safe (geom public.geometry(Geometry, 4326) ,radius numeric ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getboundariesbypointandradius(username, orgname, geom, radius, boundary_id, time_span, overlap_type); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpointsbygeometry_exception_safe (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getpointsbygeometry(username, orgname, geom, boundary_id, time_span, overlap_type); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpointsbypointandradius_exception_safe (geom public.geometry(Geometry, 4326) ,radius numeric ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getpointsbypointandradius(username, orgname, geom, radius, boundary_id, time_span, overlap_type); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeasure_exception_safe (geom public.Geometry ,measure_id text ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS numeric AS $$ +DECLARE + ret numeric; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getmeasure(username, orgname, geom, measure_id, normalize, boundary_id, time_span) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeasurebyid_exception_safe (geom_ref text ,measure_id text ,boundary_id text ,time_span text DEFAULT NULL) +RETURNS numeric AS $$ +DECLARE + ret numeric; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getmeasurebyid(username, orgname, geom_ref, measure_id, boundary_id, time_span) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata_exception_safe (geomvals geomval[] ,params json ,merge boolean DEFAULT true) +RETURNS TABLE(id int, data json) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomvals, params, merge); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata_exception_safe (geomrefs text[] ,params json) +RETURNS TABLE(id text, data json) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomrefs, params); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeta_exception_safe (geom_ref public.Geometry(Geometry, 4326) ,params json ,max_timespan_rank integer DEFAULT NULL ,max_score_rank integer DEFAULT NULL ,target_geoms integer DEFAULT NULL) +RETURNS json AS $$ +DECLARE + ret json; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_metadatavalidation_exception_safe (geom_extent public.Geometry(Geometry, 4326) ,geom_type text ,params json ,target_geoms integer DEFAULT NULL) +RETURNS TABLE(valid boolean, errors text[]) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_metadatavalidation(username, orgname, geom_extent, geom_type, params, target_geoms); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getcategory_exception_safe (geom public.Geometry ,category_id text ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS text AS $$ +DECLARE + ret text; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getcategory(username, orgname, geom, category_id, boundary_id, time_span) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getuscensusmeasure_exception_safe (geom public.Geometry ,name text ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS numeric AS $$ +DECLARE + ret numeric; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getuscensusmeasure(username, orgname, geom, name, normalize, boundary_id, time_span) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getuscensuscategory_exception_safe (geom public.Geometry ,name text ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS text AS $$ +DECLARE + ret text; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getuscensuscategory(username, orgname, geom, name, boundary_id, time_span) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpopulation_exception_safe (geom public.Geometry ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) +RETURNS numeric AS $$ +DECLARE + ret numeric; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_getpopulation(username, orgname, geom, normalize, boundary_id, time_span) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_search_exception_safe (search_term text ,relevant_boundary text DEFAULT NULL) +RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_search(username, orgname, search_term, relevant_boundary); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailableboundaries_exception_safe (geom public.Geometry ,timespan text DEFAULT NULL) +RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailableboundaries(username, orgname, geom, timespan); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_dumpversion_exception_safe () +RETURNS text AS $$ +DECLARE + ret text; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._obs_dumpversion(username, orgname) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablenumerators_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,denom_id text DEFAULT NULL ,geom_id text DEFAULT NULL ,timespan text DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailablenumerators(username, orgname, bounds, filter_tags, denom_id, geom_id, timespan); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client.__obs_getnumerators_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,section_tags text[] DEFAULT ARRAY[]::TEXT[] ,subsection_tags text[] DEFAULT ARRAY[]::TEXT[] ,other_tags text[] DEFAULT ARRAY[]::TEXT[] ,ids text[] DEFAULT ARRAY[]::TEXT[] ,name text DEFAULT NULL ,denom_id text DEFAULT '' ,geom_id text DEFAULT '' ,timespan text DEFAULT '') +RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client.__obs_getnumerators(username, orgname, bounds, section_tags, subsection_tags, other_tags, ids, name, denom_id, geom_id, timespan); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabledenominators_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,geom_id text DEFAULT NULL ,timespan text DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_denominator AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailabledenominators(username, orgname, bounds, filter_tags, numer_id, geom_id, timespan); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablegeometries_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,denom_id text DEFAULT NULL ,timespan text DEFAULT NULL ,number_geometries integer DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_geometry AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailablegeometries(username, orgname, bounds, filter_tags, numer_id, denom_id, timespan, number_geometries); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabletimespans_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,denom_id text DEFAULT NULL ,geom_id text DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_timespan AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailabletimespans(username, orgname, bounds, filter_tags, numer_id, denom_id, geom_id); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_legacybuildermetadata_exception_safe (aggregate_type text DEFAULT NULL) +RETURNS TABLE(name text, subsection json) AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN + RAISE EXCEPTION 'Data Observatory permission denied'; + END IF; + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_legacybuildermetadata(username, orgname, aggregate_type); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info_exception_safe () +RETURNS SETOF service_quota_info AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_service_quota_info(username, orgname); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info_batch_exception_safe () +RETURNS SETOF service_quota_info_batch AS $$ +DECLARE + + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_service_quota_info_batch(username, orgname); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_enough_quota_exception_safe (service TEXT ,input_size NUMERIC) +RETURNS BOOLEAN AS $$ +DECLARE + ret BOOLEAN; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_enough_quota(username, orgname, service, input_size) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_get_rate_limit_exception_safe (service text) +RETURNS json AS $$ +DECLARE + ret json; + username text; + orgname text; + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + apikey_permissions json; +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + + + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + SELECT cdb_dataservices_client._cdb_service_get_rate_limit(username, orgname, service) INTO ret; RETURN ret; + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + RETURN ret; + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_user_rate_limit_exception_safe (username text ,orgname text ,service text ,rate_limit json) +RETURNS void AS $$ +DECLARE + + + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + PERFORM cdb_dataservices_client._cdb_service_set_user_rate_limit(username, orgname, service, rate_limit); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_org_rate_limit_exception_safe (username text ,orgname text ,service text ,rate_limit json) +RETURNS void AS $$ +DECLARE + + + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + PERFORM cdb_dataservices_client._cdb_service_set_org_rate_limit(username, orgname, service, rate_limit); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +-- +-- Exception-safe private DataServices API function +-- + +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_server_rate_limit_exception_safe (username text ,orgname text ,service text ,rate_limit json) +RETURNS void AS $$ +DECLARE + + + _returned_sqlstate TEXT; + _message_text TEXT; + _pg_exception_context TEXT; + +BEGIN + IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN + RAISE EXCEPTION 'The api_key must be provided'; + END IF; + SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); + -- JSON value stored "" is taken as literal + IF username IS NULL OR username = '' OR username = '""' THEN + RAISE EXCEPTION 'Username is a mandatory argument, check it out'; + END IF; + + + BEGIN + PERFORM cdb_dataservices_client._cdb_service_set_server_rate_limit(username, orgname, service, rate_limit); + EXCEPTION + WHEN OTHERS THEN + GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, + _message_text = MESSAGE_TEXT, + _pg_exception_context = PG_EXCEPTION_CONTEXT; + RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; + + END; +END; +$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE + SET search_path = pg_temp; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_admin0_polygon (username text, orgname text, country_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin0_polygon (username text, orgname text, country_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_admin0_polygon (username, orgname, country_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, orgname text, admin1_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, orgname text, admin1_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_admin1_polygon (username, orgname, admin1_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, orgname text, admin1_name text, country_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, orgname text, admin1_name text, country_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_admin1_polygon (username, orgname, admin1_name, country_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_namedplace_point (username, orgname, city_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text, country_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text, country_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_namedplace_point (username, orgname, city_name, country_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text, admin1_name text, country_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text, admin1_name text, country_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_namedplace_point (username, orgname, city_name, admin1_name, country_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_polygon (username text, orgname text, postal_code text, country_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon (username text, orgname text, postal_code text, country_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon (username, orgname, postal_code, country_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_polygon (username text, orgname text, postal_code double precision, country_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon (username text, orgname text, postal_code double precision, country_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon (username, orgname, postal_code, country_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_point (username text, orgname text, postal_code text, country_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point (username text, orgname text, postal_code text, country_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_postalcode_point (username, orgname, postal_code, country_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_point (username text, orgname text, postal_code double precision, country_name text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point (username text, orgname text, postal_code double precision, country_name text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_postalcode_point (username, orgname, postal_code, country_name); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_ipaddress_point (username text, orgname text, ip_address text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_ipaddress_point (username text, orgname text, ip_address text) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_ipaddress_point (username, orgname, ip_address); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocode_street_point (username, orgname, searchtext, city, state_province, country); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client.__cdb_bulk_geocode_street_point (username text, orgname text, searches jsonb); +CREATE OR REPLACE FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point (username text, orgname text, searches jsonb) +RETURNS SETOF cdb_dataservices_client.geocoding AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server._cdb_bulk_geocode_street_point (username, orgname, searches); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_here_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_here_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_here_geocode_street_point (username, orgname, searchtext, city, state_province, country); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_google_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_google_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_google_geocode_street_point (username, orgname, searchtext, city, state_province, country); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_mapbox_geocode_street_point (username, orgname, searchtext, city, state_province, country); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_tomtom_geocode_street_point (username, orgname, searchtext, city, state_province, country); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocodio_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocodio_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_geocodio_geocode_street_point (username, orgname, searchtext, city, state_province, country); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapzen_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_mapzen_geocode_street_point (username, orgname, searchtext, city, state_province, country); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isodistance (username text, orgname text, source public.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, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isochrone (username text, orgname text, source public.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, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapzen_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_isochrone (username text, orgname text, source public.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_mapzen_isochrone (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) +RETURNS SETOF cdb_dataservices_client.isoline AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapzen_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_isodistance (username text, orgname text, source public.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_mapzen_isodistance (username, orgname, source, mode, range, options); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_route_point_to_point (username text, orgname text, origin public.geometry(Point, 4326), destination public.geometry(Point, 4326), mode text, options text[], units text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_point_to_point (username text, orgname text, origin public.geometry(Point, 4326), destination public.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, orgname, origin, destination, mode, options, units); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_route_with_waypoints (username text, orgname text, waypoints public.geometry(Point, 4326)[], mode text, options text[], units text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_with_waypoints (username text, orgname text, waypoints public.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_with_waypoints (username, orgname, waypoints, mode, options, units); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_get_demographic_snapshot (username text, orgname text, geom public.geometry(Geometry, 4326), time_span text, geometry_level text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_get_demographic_snapshot (username text, orgname text, geom public.geometry(Geometry, 4326), time_span text DEFAULT '2009 - 2013'::text, geometry_level text DEFAULT NULL) +RETURNS json AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_get_demographic_snapshot (username, orgname, geom, time_span, geometry_level); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_get_segment_snapshot (username text, orgname text, geom public.geometry(Geometry, 4326), geometry_level text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_get_segment_snapshot (username text, orgname text, geom public.geometry(Geometry, 4326), geometry_level text DEFAULT NULL) +RETURNS json AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_get_segment_snapshot (username, orgname, geom, geometry_level); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdemographicsnapshot (username text, orgname text, geom public.geometry(Geometry, 4326), time_span text, geometry_level text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdemographicsnapshot (username text, orgname text, geom public.geometry(Geometry, 4326), time_span text DEFAULT NULL, geometry_level text DEFAULT NULL) +RETURNS SETOF JSON AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getdemographicsnapshot (username, orgname, geom, time_span, geometry_level); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getsegmentsnapshot (username text, orgname text, geom public.geometry(Geometry, 4326), geometry_level text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getsegmentsnapshot (username text, orgname text, geom public.geometry(Geometry, 4326), geometry_level text DEFAULT NULL) +RETURNS SETOF JSON AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getsegmentsnapshot (username, orgname, geom, geometry_level); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundary (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundary (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text DEFAULT NULL) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getboundary (username, orgname, geom, boundary_id, time_span); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundaryid (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundaryid (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text DEFAULT NULL) +RETURNS text AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getboundaryid (username, orgname, geom, boundary_id, time_span); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundarybyid (username text, orgname text, geometry_id text, boundary_id text, time_span text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundarybyid (username text, orgname text, geometry_id text, boundary_id text, time_span text DEFAULT NULL) +RETURNS public.Geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getboundarybyid (username, orgname, geometry_id, boundary_id, time_span); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundariesbygeometry (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundariesbygeometry (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text DEFAULT NULL, overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getboundariesbygeometry (username, orgname, geom, boundary_id, time_span, overlap_type); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundariesbypointandradius (username text, orgname text, geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundariesbypointandradius (username text, orgname text, geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text DEFAULT NULL, overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getboundariesbypointandradius (username, orgname, geom, radius, boundary_id, time_span, overlap_type); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getpointsbygeometry (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpointsbygeometry (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text DEFAULT NULL, overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getpointsbygeometry (username, orgname, geom, boundary_id, time_span, overlap_type); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getpointsbypointandradius (username text, orgname text, geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpointsbypointandradius (username text, orgname text, geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text DEFAULT NULL, overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getpointsbypointandradius (username, orgname, geom, radius, boundary_id, time_span, overlap_type); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeasure (username text, orgname text, geom public.Geometry, measure_id text, normalize text, boundary_id text, time_span text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeasure (username text, orgname text, geom public.Geometry, measure_id text, normalize text DEFAULT NULL, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) +RETURNS numeric AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getmeasure (username, orgname, geom, measure_id, normalize, boundary_id, time_span); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeasurebyid (username text, orgname text, geom_ref text, measure_id text, boundary_id text, time_span text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeasurebyid (username text, orgname text, geom_ref text, measure_id text, boundary_id text, time_span text DEFAULT NULL) +RETURNS numeric AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getmeasurebyid (username, orgname, geom_ref, measure_id, boundary_id, time_span); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata (username text, orgname text, geomvals geomval[], params json, merge boolean); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata (username text, orgname text, geomvals geomval[], params json, merge boolean DEFAULT true) +RETURNS TABLE(id int, data json) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getdata (username, orgname, geomvals, params, merge); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata (username text, orgname text, geomrefs text[], params json); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata (username text, orgname text, geomrefs text[], params json) +RETURNS TABLE(id text, data json) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getdata (username, orgname, geomrefs, params); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeta (username text, orgname text, geom_ref public.Geometry(Geometry, 4326), params json, max_timespan_rank integer, max_score_rank integer, target_geoms integer); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeta (username text, orgname text, geom_ref public.Geometry(Geometry, 4326), params json, max_timespan_rank integer DEFAULT NULL, max_score_rank integer DEFAULT NULL, target_geoms integer DEFAULT NULL) +RETURNS json AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getmeta (username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_metadatavalidation (username text, orgname text, geom_extent public.Geometry(Geometry, 4326), geom_type text, params json, target_geoms integer); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_metadatavalidation (username text, orgname text, geom_extent public.Geometry(Geometry, 4326), geom_type text, params json, target_geoms integer DEFAULT NULL) +RETURNS TABLE(valid boolean, errors text[]) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_metadatavalidation (username, orgname, geom_extent, geom_type, params, target_geoms); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getcategory (username text, orgname text, geom public.Geometry, category_id text, boundary_id text, time_span text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getcategory (username text, orgname text, geom public.Geometry, category_id text, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) +RETURNS text AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getcategory (username, orgname, geom, category_id, boundary_id, time_span); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getuscensusmeasure (username text, orgname text, geom public.Geometry, name text, normalize text, boundary_id text, time_span text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getuscensusmeasure (username text, orgname text, geom public.Geometry, name text, normalize text DEFAULT NULL, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) +RETURNS numeric AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getuscensusmeasure (username, orgname, geom, name, normalize, boundary_id, time_span); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getuscensuscategory (username text, orgname text, geom public.Geometry, name text, boundary_id text, time_span text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getuscensuscategory (username text, orgname text, geom public.Geometry, name text, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) +RETURNS text AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getuscensuscategory (username, orgname, geom, name, boundary_id, time_span); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getpopulation (username text, orgname text, geom public.Geometry, normalize text, boundary_id text, time_span text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpopulation (username text, orgname text, geom public.Geometry, normalize text DEFAULT NULL, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) +RETURNS numeric AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_getpopulation (username, orgname, geom, normalize, boundary_id, time_span); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_search (username text, orgname text, search_term text, relevant_boundary text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_search (username text, orgname text, search_term text, relevant_boundary text DEFAULT NULL) +RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_search (username, orgname, search_term, relevant_boundary); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailableboundaries (username text, orgname text, geom public.Geometry, timespan text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailableboundaries (username text, orgname text, geom public.Geometry, timespan text DEFAULT NULL) +RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getavailableboundaries (username, orgname, geom, timespan); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_dumpversion (username text, orgname text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_dumpversion (username text, orgname text) +RETURNS text AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.obs_dumpversion (username, orgname); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailablenumerators (username text, orgname text, bounds public.geometry(Geometry, 4326), filter_tags text[], denom_id text, geom_id text, timespan text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablenumerators (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, denom_id text DEFAULT NULL, geom_id text DEFAULT NULL, timespan text DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getavailablenumerators (username, orgname, bounds, filter_tags, denom_id, geom_id, timespan); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client.__obs_getnumerators (username text, orgname text, bounds public.geometry(Geometry, 4326), section_tags text[], subsection_tags text[], other_tags text[], ids text[], name text, denom_id text, geom_id text, timespan text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client.__obs_getnumerators (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, section_tags text[] DEFAULT ARRAY[]::TEXT[], subsection_tags text[] DEFAULT ARRAY[]::TEXT[], other_tags text[] DEFAULT ARRAY[]::TEXT[], ids text[] DEFAULT ARRAY[]::TEXT[], name text DEFAULT NULL, denom_id text DEFAULT '', geom_id text DEFAULT '', timespan text DEFAULT '') +RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server._obs_getnumerators (username, orgname, bounds, section_tags, subsection_tags, other_tags, ids, name, denom_id, geom_id, timespan); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailabledenominators (username text, orgname text, bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, geom_id text, timespan text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabledenominators (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, geom_id text DEFAULT NULL, timespan text DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_denominator AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getavailabledenominators (username, orgname, bounds, filter_tags, numer_id, geom_id, timespan); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailablegeometries (username text, orgname text, bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, timespan text, number_geometries integer); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablegeometries (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, denom_id text DEFAULT NULL, timespan text DEFAULT NULL, number_geometries integer DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_geometry AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getavailablegeometries (username, orgname, bounds, filter_tags, numer_id, denom_id, timespan, number_geometries); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailabletimespans (username text, orgname text, bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, geom_id text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabletimespans (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, denom_id text DEFAULT NULL, geom_id text DEFAULT NULL) +RETURNS SETOF cdb_dataservices_client.obs_meta_timespan AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_getavailabletimespans (username, orgname, bounds, filter_tags, numer_id, denom_id, geom_id); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_legacybuildermetadata (username text, orgname text, aggregate_type text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_legacybuildermetadata (username text, orgname text, aggregate_type text DEFAULT NULL) +RETURNS TABLE(name text, subsection json) AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.obs_legacybuildermetadata (username, orgname, aggregate_type); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_quota_info (username text, orgname text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info (username text, orgname text) +RETURNS SETOF service_quota_info AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_service_quota_info (username, orgname); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_quota_info_batch (username text, orgname text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info_batch (username text, orgname text) +RETURNS SETOF service_quota_info_batch AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT * FROM cdb_dataservices_server.cdb_service_quota_info_batch (username, orgname); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_enough_quota (username text, orgname text, service TEXT, input_size NUMERIC); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_enough_quota (username text, orgname text, service TEXT, input_size NUMERIC) +RETURNS BOOLEAN AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_enough_quota (username, orgname, service, input_size); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_get_rate_limit (username text, orgname text, service text); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_get_rate_limit (username text, orgname text, service text) +RETURNS json AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_service_get_rate_limit (username, orgname, service); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_set_user_rate_limit (username text, orgname text, service text, rate_limit json); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_user_rate_limit (username text, orgname text, service text, rate_limit json) +RETURNS void AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_service_set_user_rate_limit (username, orgname, service, rate_limit); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_set_org_rate_limit (username text, orgname text, service text, rate_limit json); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_org_rate_limit (username text, orgname text, service text, rate_limit json) +RETURNS void AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_service_set_org_rate_limit (username, orgname, service, rate_limit); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_set_server_rate_limit (username text, orgname text, service text, rate_limit json); +CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_server_rate_limit (username text, orgname text, service text, rate_limit json) +RETURNS void AS $$ + CONNECT cdb_dataservices_client._server_conn_str(); + + SELECT cdb_dataservices_server.cdb_service_set_server_rate_limit (username, orgname, service, rate_limit); + +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +CREATE OR REPLACE FUNCTION cdb_dataservices_client._OBS_PreCheck( + source_query text, + parameters json +) RETURNS boolean AS $$ +DECLARE + errors text[]; + validator_errors text[]; + validator_error text; + valid boolean; + geoms record; +BEGIN + errors := (ARRAY[])::TEXT[]; + FOR geoms IN EXECUTE format('SELECT ST_GeometryType(the_geom) as geom_type, + bool_and(st_isvalid(the_geom)) as valid, + avg(st_npoints(the_geom)) as avg_vertex, + ST_SetSRID(ST_Extent(the_geom), 4326) as extent, + count(*)::INT as numgeoms + FROM (%s) as _source + GROUP BY ST_GeometryType(the_geom)', source_query) + LOOP + IF geoms.geom_type NOT IN ('ST_Polygon', 'ST_MultiPolygon', 'ST_Point') THEN + errors := array_append(errors, format($data$'Geometry type %s not supported'$data$, geoms.geom_type)); + END IF; + + IF geoms.valid IS FALSE THEN + errors := array_append(errors, 'There are invalid geometries in the input data, please try to fix them'); + END IF; + + -- 1000 vertex for a geometry is a limit we have in the obs_getdata function. You can check here + -- https://github.com/CartoDB/observatory-extension/blob/1.6.0/src/pg/sql/41_observatory_augmentation.sql#L813 + IF geoms.avg_vertex > 1000 THEN + errors := array_append(errors, 'The average number of vertices per geometry is greater than 1000, please try to simplify them'); + END IF; + + -- OBS specific part + EXECUTE 'SELECT valid, errors + FROM cdb_dataservices_client.OBS_MetadataValidation($1, $2, $3, $4)' + INTO valid, validator_errors + USING geoms.extent, geoms.geom_type, parameters, geoms.numgeoms; + IF valid is FALSE THEN + FOR validator_error IN EXECUTE 'SELECT unnest($1)' USING validator_errors + LOOP + errors := array_append(errors, validator_error); + END LOOP; + END IF; + END LOOP; + + IF CARDINALITY(errors) > 0 THEN + RAISE EXCEPTION '%', errors; + END IF; + + RETURN TRUE; +END; +$$ LANGUAGE 'plpgsql' VOLATILE PARALLEL UNSAFE; +-- 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_admin0_polygon_exception_safe(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_exception_safe(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_admin1_polygon_exception_safe(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_exception_safe(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_exception_safe(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_namedplace_point_exception_safe(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_polygon_exception_safe(postal_code text, country_name text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_polygon(postal_code double precision, country_name text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon_exception_safe(postal_code double precision, 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_postalcode_point_exception_safe(postal_code text, country_name text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_point(postal_code double precision, country_name text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point_exception_safe(postal_code double precision, 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_ipaddress_point_exception_safe(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_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point(searches jsonb) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point_exception_safe(searches jsonb ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_here_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_here_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_google_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_google_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocodio_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_geocodio_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapzen_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapzen_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapzen_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapzen_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapzen_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapzen_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_route_point_to_point(origin public.geometry(Point, 4326), destination public.geometry(Point, 4326), mode text, options text[], units text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_route_point_to_point_exception_safe(origin public.geometry(Point, 4326), destination public.geometry(Point, 4326), mode text, options text[], units text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_route_with_waypoints(waypoints public.geometry(Point, 4326)[], mode text, options text[], units text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_route_with_waypoints_exception_safe(waypoints public.geometry(Point, 4326)[], mode text, options text[], units text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_get_demographic_snapshot(geom public.geometry(Geometry, 4326), time_span text, geometry_level text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_get_demographic_snapshot_exception_safe(geom public.geometry(Geometry, 4326), time_span text, geometry_level text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_get_segment_snapshot(geom public.geometry(Geometry, 4326), geometry_level text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_get_segment_snapshot_exception_safe(geom public.geometry(Geometry, 4326), geometry_level text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getdemographicsnapshot(geom public.geometry(Geometry, 4326), time_span text, geometry_level text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getdemographicsnapshot_exception_safe(geom public.geometry(Geometry, 4326), time_span text, geometry_level text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getsegmentsnapshot(geom public.geometry(Geometry, 4326), geometry_level text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getsegmentsnapshot_exception_safe(geom public.geometry(Geometry, 4326), geometry_level text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundary(geom public.geometry(Geometry, 4326), boundary_id text, time_span text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundary_exception_safe(geom public.geometry(Geometry, 4326), boundary_id text, time_span text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundaryid(geom public.geometry(Geometry, 4326), boundary_id text, time_span text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundaryid_exception_safe(geom public.geometry(Geometry, 4326), boundary_id text, time_span text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundarybyid(geometry_id text, boundary_id text, time_span text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundarybyid_exception_safe(geometry_id text, boundary_id text, time_span text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundariesbygeometry(geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundariesbygeometry_exception_safe(geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundariesbypointandradius(geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundariesbypointandradius_exception_safe(geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getpointsbygeometry(geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getpointsbygeometry_exception_safe(geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getpointsbypointandradius(geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getpointsbypointandradius_exception_safe(geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getmeasure(geom public.Geometry, measure_id text, normalize text, boundary_id text, time_span text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getmeasure_exception_safe(geom public.Geometry, measure_id text, normalize text, boundary_id text, time_span text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getmeasurebyid(geom_ref text, measure_id text, boundary_id text, time_span text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getmeasurebyid_exception_safe(geom_ref text, measure_id text, boundary_id text, time_span text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getdata(geomvals geomval[], params json, merge boolean) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getdata_exception_safe(geomvals geomval[], params json, merge boolean ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getdata(geomrefs text[], params json) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getdata_exception_safe(geomrefs text[], params json ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getmeta(geom_ref public.Geometry(Geometry, 4326), params json, max_timespan_rank integer, max_score_rank integer, target_geoms integer) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getmeta_exception_safe(geom_ref public.Geometry(Geometry, 4326), params json, max_timespan_rank integer, max_score_rank integer, target_geoms integer ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_metadatavalidation(geom_extent public.Geometry(Geometry, 4326), geom_type text, params json, target_geoms integer) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_metadatavalidation_exception_safe(geom_extent public.Geometry(Geometry, 4326), geom_type text, params json, target_geoms integer ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getcategory(geom public.Geometry, category_id text, boundary_id text, time_span text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getcategory_exception_safe(geom public.Geometry, category_id text, boundary_id text, time_span text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getuscensusmeasure(geom public.Geometry, name text, normalize text, boundary_id text, time_span text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getuscensusmeasure_exception_safe(geom public.Geometry, name text, normalize text, boundary_id text, time_span text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getuscensuscategory(geom public.Geometry, name text, boundary_id text, time_span text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getuscensuscategory_exception_safe(geom public.Geometry, name text, boundary_id text, time_span text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getpopulation(geom public.Geometry, normalize text, boundary_id text, time_span text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getpopulation_exception_safe(geom public.Geometry, normalize text, boundary_id text, time_span text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_search(search_term text, relevant_boundary text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_search_exception_safe(search_term text, relevant_boundary text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailableboundaries(geom public.Geometry, timespan text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailableboundaries_exception_safe(geom public.Geometry, timespan text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_dumpversion() TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_dumpversion_exception_safe( ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailablenumerators(bounds public.geometry(Geometry, 4326), filter_tags text[], denom_id text, geom_id text, timespan text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailablenumerators_exception_safe(bounds public.geometry(Geometry, 4326), filter_tags text[], denom_id text, geom_id text, timespan text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getnumerators(bounds public.geometry(Geometry, 4326), section_tags text[], subsection_tags text[], other_tags text[], ids text[], name text, denom_id text, geom_id text, timespan text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.__obs_getnumerators_exception_safe(bounds public.geometry(Geometry, 4326), section_tags text[], subsection_tags text[], other_tags text[], ids text[], name text, denom_id text, geom_id text, timespan text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailabledenominators(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, geom_id text, timespan text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailabledenominators_exception_safe(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, geom_id text, timespan text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailablegeometries(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, timespan text, number_geometries integer) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailablegeometries_exception_safe(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, timespan text, number_geometries integer ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailabletimespans(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, geom_id text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailabletimespans_exception_safe(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, geom_id text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_legacybuildermetadata(aggregate_type text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_legacybuildermetadata_exception_safe(aggregate_type text ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_service_quota_info() TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_service_quota_info_exception_safe( ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch() TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_service_quota_info_batch_exception_safe( ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_enough_quota(service TEXT, input_size NUMERIC) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_enough_quota_exception_safe(service TEXT, input_size NUMERIC ) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_service_get_rate_limit(service text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_service_get_rate_limit_exception_safe(service text ) TO publicuser; + + + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PrepareTableOBS_GetMeasure(output_table_name text, params json) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PopulateTableOBS_GetMeasure(table_name text, output_table_name text, params json) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client._OBS_PreCheck(source_query text, params JSON) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point(query text, street_column text, city_column text, state_column text, country_column text, batch_size integer) TO publicuser; + +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_count_estimate(query text) TO publicuser; +GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_jsonb_array_casttext(jsonb) TO publicuser; diff --git a/client/cdb_dataservices_client.control b/client/cdb_dataservices_client.control index 395c212..ebf1daf 100644 --- a/client/cdb_dataservices_client.control +++ b/client/cdb_dataservices_client.control @@ -1,5 +1,5 @@ comment = 'CartoDB dataservices client API extension' -default_version = '0.28.0' +default_version = '0.29.0' requires = 'plproxy, cartodb' superuser = true schema = cdb_dataservices_client diff --git a/client/cdb_dataservices_client--0.27.0--0.28.0.sql b/client/old_versions/cdb_dataservices_client--0.27.0--0.28.0.sql similarity index 100% rename from client/cdb_dataservices_client--0.27.0--0.28.0.sql rename to client/old_versions/cdb_dataservices_client--0.27.0--0.28.0.sql diff --git a/client/cdb_dataservices_client--0.28.0--0.27.0.sql b/client/old_versions/cdb_dataservices_client--0.28.0--0.27.0.sql similarity index 100% rename from client/cdb_dataservices_client--0.28.0--0.27.0.sql rename to client/old_versions/cdb_dataservices_client--0.28.0--0.27.0.sql diff --git a/client/cdb_dataservices_client--0.28.0.sql b/client/old_versions/cdb_dataservices_client--0.28.0.sql similarity index 100% rename from client/cdb_dataservices_client--0.28.0.sql rename to client/old_versions/cdb_dataservices_client--0.28.0.sql From 3eb36f99bb896e20d78f3178fe48c6caf7431f9c Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Mon, 10 Feb 2020 10:13:42 +0100 Subject: [PATCH 06/20] Added mapbox_iso isolines provider to config --- .../python/cartodb_services/cartodb_services/metrics/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py index 55b70b4..136d37b 100644 --- a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py +++ b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py @@ -224,7 +224,7 @@ class IsolinesRoutingConfig(ServiceConfig): GEOCODER_PROVIDER_KEY = 'geocoder_provider' MAPZEN_PROVIDER = 'mapzen' MAPBOX_PROVIDER = 'mapbox' - MAPBOX_ISO_PROVIDER = 'mapbox' + MAPBOX_ISO_PROVIDER = 'mapbox_iso' TOMTOM_PROVIDER = 'tomtom' HEREMAPS_PROVIDER = 'heremaps' DEFAULT_PROVIDER = MAPBOX_PROVIDER From 8f823a5faed33dcb1ecb4767ffc769b2be089ec5 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Mon, 10 Feb 2020 10:27:11 +0100 Subject: [PATCH 07/20] Fixed error --- .../cartodb_services/cartodb_services/metrics/config.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py index 136d37b..f767b5d 100644 --- a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py +++ b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py @@ -712,9 +712,9 @@ class ServicesDBConfig: raise ConfigException('Mapbox True Isochrones configuration missing') mapbox_iso_conf = json.loads(mapbox_iso_conf_json) - self._mapbox_iso_isolines_api_keys = mapbox_conf['isolines']['api_keys'] - self._mapbox_iso_isolines_quota = tomtom_conf['isolines']['monthly_quota'] - self._mapbox_iso_isolines_service_params = tomtom_conf.get('isolines', {}).get('service', {}) + self._mapbox_iso_isolines_api_keys = mapbox_iso_conf['isolines']['api_keys'] + self._mapbox_iso_isolines_quota = mapbox_iso_conf['isolines']['monthly_quota'] + self._mapbox_iso_isolines_service_params = mapbox_iso_conf.get('isolines', {}).get('service', {}) def _get_tomtom_config(self): tomtom_conf_json = self._get_conf('tomtom_conf') From 80c1433bbd7f3256c59a0ebf8cb319225b816cbc Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Mon, 10 Feb 2020 11:51:13 +0100 Subject: [PATCH 08/20] Fix error --- .../refactor/service/mapbox_true_isolines_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py b/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py index d0864f2..7dbb445 100644 --- a/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py +++ b/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py @@ -1,6 +1,6 @@ from dateutil.parser import parse as date_parse from cartodb_services.refactor.service.utils import round_robin -from cartodb_services.mapbox.types import MAPBOX_ISOLINES_APIKEY_ROUNDROBIN +from cartodb_services.mapbox.types import MAPBOX_ISO_ISOLINES_APIKEY_ROUNDROBIN class MapboxTrueIsolinesConfig(object): From cd366d758998d8cfbda94cd100bbc02b2cc6fc60 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Mon, 10 Feb 2020 13:07:21 +0100 Subject: [PATCH 09/20] Extracting correct coordinates --- .../cartodb_services/mapbox/true_isolines.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py index 2fa53c6..0bb6b34 100644 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py @@ -25,6 +25,7 @@ VALID_PROFILES = [PROFILE_DRIVING, ENTRY_FEATURES = 'features' ENTRY_GEOMETRY = 'geometry' +ENTRY_COORDINATES = 'coordinates' class MapboxTrueIsolines(): @@ -53,7 +54,8 @@ class MapboxTrueIsolines(): [x for x in VALID_PROFILES]))) def _parse_coordinates(self, boundary): - return [Coordinate(c[0], c[1]) for c in boundary] + coordinates = boundary.get(ENTRY_COORDINATES, []) + return [Coordinate(c[0], c[1]) for c in coordinates] def _parse_isochrone_service(self, response): json_response = json.loads(response) @@ -82,7 +84,6 @@ class MapboxTrueIsolines(): if response.status_code == requests.codes.ok: isolines = [] - coordinates = self._parse_isochrone_service(response.text) for t, c in zip(time_ranges, coordinates): isolines.append(MapboxTrueIsochronesResponse(c, t)) From d5efc681e4d663d00fcae8f081f03d237e8e5bd0 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Mon, 10 Feb 2020 13:18:24 +0100 Subject: [PATCH 10/20] Validate time ranges --- .../cartodb_services/mapbox/true_isolines.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py index 0bb6b34..251b8dd 100644 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py @@ -13,6 +13,9 @@ PROFILE_CYCLING = 'cycling' PROFILE_WALKING = 'walking' DEFAULT_PROFILE = PROFILE_DRIVING +MAX_TIME_RANGE = 60 * 60 # The maximum time that can be specified is 60 minutes. + # https://docs.mapbox.com/api/navigation/#retrieve-isochrones-around-a-location + MAX_SPEEDS = { PROFILE_WALKING: 3.3333333, # In m/s, assuming 12km/h walking speed PROFILE_CYCLING: 16.67, # In m/s, assuming 60km/h max speed @@ -53,6 +56,12 @@ class MapboxTrueIsolines(): valid_profiles=', '.join( [x for x in VALID_PROFILES]))) + def _validate_time_ranges(self, time_ranges): + for time_range in time_ranges: + if time_range > MAX_TIME_RANGE: + raise ValueError('Cannot query time ranges greater than {max_time_range} seconds'.format( + max_time_range=MAX_TIME_RANGE)) + def _parse_coordinates(self, boundary): coordinates = boundary.get(ENTRY_COORDINATES, []) return [Coordinate(c[0], c[1]) for c in coordinates] @@ -71,6 +80,8 @@ class MapboxTrueIsolines(): @qps_retry(qps=5, provider='mapbox_iso') def _calculate_isoline(self, origin, time_ranges, profile=DEFAULT_PROFILE): + self._validate_time_ranges(time_ranges) + origin = '{lon},{lat}'.format(lat=origin.latitude, lon=origin.longitude) From e696fa2d398eb331cd5e25b2085b9d5c1e892aa1 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Mon, 10 Feb 2020 13:18:45 +0100 Subject: [PATCH 11/20] Add test to validate time ranges --- .../cartodb_services/test/test_mapboxtrueisoline.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py b/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py index cc9dd9c..229496f 100644 --- a/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py +++ b/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py @@ -14,6 +14,15 @@ class MapboxTrueIsolinesTestCase(unittest.TestCase): self.mapbox_isolines = MapboxTrueIsolines(apikey=mapbox_api_key(), logger=Mock()) + def test_invalid_time_range(self): + time_ranges = [4000] + + with self.assertRaises(ValueError): + solution = self.mapbox_isolines.calculate_isochrone( + origin=VALID_ORIGIN, + profile=DEFAULT_PROFILE, + time_ranges=time_ranges) + def test_calculate_isochrone(self): time_ranges = [300, 900] solution = self.mapbox_isolines.calculate_isochrone( From 02d705465c4561fb52feebdf0e162bb4f35fceb8 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Mon, 10 Feb 2020 15:45:51 +0100 Subject: [PATCH 12/20] Removed unneeded message --- client/cdb_dataservices_client--0.28.0--0.29.0.sql | 1 - client/cdb_dataservices_client--0.29.0--0.28.0.sql | 1 - server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql | 1 - server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql | 1 - 4 files changed, 4 deletions(-) diff --git a/client/cdb_dataservices_client--0.28.0--0.29.0.sql b/client/cdb_dataservices_client--0.28.0--0.29.0.sql index 4808b5c..7268146 100644 --- a/client/cdb_dataservices_client--0.28.0--0.29.0.sql +++ b/client/cdb_dataservices_client--0.28.0--0.29.0.sql @@ -1,4 +1,3 @@ ---DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES -- Complain if script is sourced in psql, rather than via CREATE EXTENSION \echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.29.0'" to load this file. \quit diff --git a/client/cdb_dataservices_client--0.29.0--0.28.0.sql b/client/cdb_dataservices_client--0.29.0--0.28.0.sql index 8e742d8..e27ddd2 100644 --- a/client/cdb_dataservices_client--0.29.0--0.28.0.sql +++ b/client/cdb_dataservices_client--0.29.0--0.28.0.sql @@ -1,4 +1,3 @@ ---DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES -- Complain if script is sourced in psql, rather than via CREATE EXTENSION \echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.28.0'" to load this file. \quit diff --git a/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql b/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql index c1fb862..79da431 100644 --- a/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql +++ b/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql @@ -1,4 +1,3 @@ ---DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES -- Complain if script is sourced in psql, rather than via CREATE EXTENSION \echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.37.0'" to load this file. \quit diff --git a/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql b/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql index 3352fb4..e418cbc 100644 --- a/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql +++ b/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql @@ -1,4 +1,3 @@ ---DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES -- Complain if script is sourced in psql, rather than via CREATE EXTENSION \echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.36.0'" to load this file. \quit From 62cbed7f17b6de4487a441b23075363ac6ae3135 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Mon, 10 Feb 2020 16:56:17 +0100 Subject: [PATCH 13/20] Fixed speed --- .../cartodb_services/cartodb_services/mapbox/true_isolines.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py index 251b8dd..89208f1 100644 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py @@ -19,7 +19,7 @@ MAX_TIME_RANGE = 60 * 60 # The maximum time that can be specified is 60 minutes MAX_SPEEDS = { PROFILE_WALKING: 3.3333333, # In m/s, assuming 12km/h walking speed PROFILE_CYCLING: 16.67, # In m/s, assuming 60km/h max speed - PROFILE_DRIVING: 41.67 # In m/s, assuming 140km/h max speed + PROFILE_DRIVING: 38.89 # In m/s, assuming 140km/h max speed } VALID_PROFILES = [PROFILE_DRIVING, From 484a05dbd98ef6b98d137bd185a5b2432770cfea Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Tue, 11 Feb 2020 09:58:04 +0100 Subject: [PATCH 14/20] Deleted new client version --- README.md | 11 +- ...db_dataservices_client--0.27.0--0.28.0.sql | 0 ...db_dataservices_client--0.28.0--0.27.0.sql | 0 ...db_dataservices_client--0.28.0--0.29.0.sql | 160 - .../cdb_dataservices_client--0.28.0.sql | 0 ...db_dataservices_client--0.29.0--0.28.0.sql | 19 - client/cdb_dataservices_client--0.29.0.sql | 5983 ----------------- client/cdb_dataservices_client.control | 2 +- client/renderer/interface.yaml | 26 - 9 files changed, 2 insertions(+), 6199 deletions(-) rename client/{old_versions => }/cdb_dataservices_client--0.27.0--0.28.0.sql (100%) rename client/{old_versions => }/cdb_dataservices_client--0.28.0--0.27.0.sql (100%) delete mode 100644 client/cdb_dataservices_client--0.28.0--0.29.0.sql rename client/{old_versions => }/cdb_dataservices_client--0.28.0.sql (100%) delete mode 100644 client/cdb_dataservices_client--0.29.0--0.28.0.sql delete mode 100644 client/cdb_dataservices_client--0.29.0.sql diff --git a/README.md b/README.md index a06ebcf..faa6ef5 100644 --- a/README.md +++ b/README.md @@ -167,16 +167,7 @@ SELECT CDB_Conf_SetConf( ```sql SELECT CDB_Conf_SetConf( 'mapbox_conf', - '{"routing": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "geocoder": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "matrix": {"api_keys": ["your_api_key"], "monthly_quota": 1500000}}' -); -``` - -#### Mapbox true isolines configuration - -```sql -SELECT CDB_Conf_SetConf( - 'mapbox_iso_conf', - '{"isolines": {"api_keys": ["your_api_key"], "monthly_quota": 1500000}}' + '{"routing": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "geocoder": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "isolines": {"api_keys": ["your_api_key"], "monthly_quota": 1500000}}' ); ``` diff --git a/client/old_versions/cdb_dataservices_client--0.27.0--0.28.0.sql b/client/cdb_dataservices_client--0.27.0--0.28.0.sql similarity index 100% rename from client/old_versions/cdb_dataservices_client--0.27.0--0.28.0.sql rename to client/cdb_dataservices_client--0.27.0--0.28.0.sql diff --git a/client/old_versions/cdb_dataservices_client--0.28.0--0.27.0.sql b/client/cdb_dataservices_client--0.28.0--0.27.0.sql similarity index 100% rename from client/old_versions/cdb_dataservices_client--0.28.0--0.27.0.sql rename to client/cdb_dataservices_client--0.28.0--0.27.0.sql diff --git a/client/cdb_dataservices_client--0.28.0--0.29.0.sql b/client/cdb_dataservices_client--0.28.0--0.29.0.sql deleted file mode 100644 index 7268146..0000000 --- a/client/cdb_dataservices_client--0.28.0--0.29.0.sql +++ /dev/null @@ -1,160 +0,0 @@ --- Complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.29.0'" to load this file. \quit - --- Make sure we have a sane search path to create/update the extension -SET search_path = "$user",cartodb,public,cdb_dataservices_client; - --- HERE goes your code to upgrade/downgrade - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isochrone(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isodistance(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isochrone(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isodistance(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; - - -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - - -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; diff --git a/client/old_versions/cdb_dataservices_client--0.28.0.sql b/client/cdb_dataservices_client--0.28.0.sql similarity index 100% rename from client/old_versions/cdb_dataservices_client--0.28.0.sql rename to client/cdb_dataservices_client--0.28.0.sql diff --git a/client/cdb_dataservices_client--0.29.0--0.28.0.sql b/client/cdb_dataservices_client--0.29.0--0.28.0.sql deleted file mode 100644 index e27ddd2..0000000 --- a/client/cdb_dataservices_client--0.29.0--0.28.0.sql +++ /dev/null @@ -1,19 +0,0 @@ --- Complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.28.0'" to load this file. \quit - --- Make sure we have a sane search path to create/update the extension -SET search_path = "$user",cartodb,public,cdb_dataservices_client; - --- HERE goes your code to upgrade/downgrade - -DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_mapbox_iso_isochrone; - -DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_mapbox_iso_isodistance; - -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe; - -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe; - -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isochrone; - -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isodistance; diff --git a/client/cdb_dataservices_client--0.29.0.sql b/client/cdb_dataservices_client--0.29.0.sql deleted file mode 100644 index 14a6cf4..0000000 --- a/client/cdb_dataservices_client--0.29.0.sql +++ /dev/null @@ -1,5983 +0,0 @@ ---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 - --- Make sure we have a sane search path to create/update the extension -SET search_path = "$user",cartodb,public,cdb_dataservices_client; --- Taken from https://wiki.postgresql.org/wiki/Count_estimate -CREATE FUNCTION cdb_dataservices_client.cdb_count_estimate(query text) RETURNS INTEGER AS -$func$ -DECLARE - rec record; - ROWS INTEGER; -BEGIN - FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP - ROWS := SUBSTRING(rec."QUERY PLAN" FROM ' rows=([[:digit:]]+)'); - EXIT WHEN ROWS IS NOT NULL; - END LOOP; - - RETURN ROWS; -END -$func$ LANGUAGE plpgsql; - --- Taken from https://stackoverflow.com/a/48013356/351721 -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_jsonb_array_casttext(jsonb) RETURNS text[] AS $f$ - SELECT array_agg(x) || ARRAY[]::text[] FROM jsonb_array_elements_text($1) t(x); -$f$ LANGUAGE sql IMMUTABLE;-- --- 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' STABLE PARALLEL SAFE; -CREATE TYPE cdb_dataservices_client._entity_config AS ( - username text, - organization_name text, - apikey_permissions json -); - --- --- 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; - apikey_config json; - is_organization boolean; - organization_name text DEFAULT NULL; -BEGIN - SELECT cartodb.cdb_conf_getconf('api_keys_'||session_user) INTO apikey_config; - - 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 cartodb.cdb_conf_getconf('user_config')->>'entity_name' INTO organization_name; - END IF; - result.username = apikey_config->>'username'; - result.organization_name = organization_name; - result.apikey_permissions = apikey_config->'permissions'; - RETURN result; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL SAFE - SET search_path = pg_temp; - -CREATE TYPE cdb_dataservices_client.isoline AS ( - center geometry(Geometry,4326), - data_range integer, - the_geom geometry(Multipolygon,4326) -); - -CREATE TYPE cdb_dataservices_client.geocoding AS ( - cartodb_id integer, - the_geom geometry(Point,4326), - metadata jsonb -); - -CREATE TYPE cdb_dataservices_client.simple_route AS ( - shape geometry(LineString,4326), - length real, - duration integer -); - --- For the OBS_Meta functions -CREATE TYPE cdb_dataservices_client.obs_meta_numerator AS (numer_id text, numer_name text, numer_description text, numer_weight text, numer_license text, numer_source text, numer_type text, numer_aggregate text, numer_extra jsonb, numer_tags jsonb, valid_denom boolean, valid_geom boolean, valid_timespan boolean); - -CREATE TYPE cdb_dataservices_client.obs_meta_denominator AS (denom_id text, denom_name text, denom_description text, denom_weight text, denom_license text, denom_source text, denom_type text, denom_aggregate text, denom_extra jsonb, denom_tags jsonb, valid_numer boolean, valid_geom boolean, valid_timespan boolean); - -CREATE TYPE cdb_dataservices_client.obs_meta_geometry AS (geom_id text, geom_name text, geom_description text, geom_weight text, geom_aggregate text, geom_license text, geom_source text, valid_numer boolean, valid_denom boolean, valid_timespan boolean, score numeric, numtiles bigint, notnull_percent numeric, numgeoms numeric, percentfill numeric, estnumgeoms numeric, meanmediansize numeric, geom_type text, geom_extra jsonb, geom_tags jsonb); - -CREATE TYPE cdb_dataservices_client.obs_meta_timespan AS (timespan_id text, timespan_name text, timespan_description text, timespan_weight text, timespan_aggregate text, timespan_license text, timespan_source text, valid_numer boolean, valid_denom boolean, valid_geom boolean, timespan_type text, timespan_extra jsonb, timespan_tags jsonb); - - --- For quotas and services configuration -CREATE TYPE cdb_dataservices_client.service_type AS ENUM ( - 'isolines', - 'hires_geocoder', - 'routing', - 'observatory' -); - -CREATE TYPE cdb_dataservices_client.service_quota_info AS ( - service cdb_dataservices_client.service_type, - monthly_quota NUMERIC, - used_quota NUMERIC, - soft_limit BOOLEAN, - provider TEXT -); - -CREATE TYPE cdb_dataservices_client.service_quota_info_batch AS ( - service cdb_dataservices_client.service_type, - monthly_quota NUMERIC, - used_quota NUMERIC, - soft_limit BOOLEAN, - provider TEXT, - max_batch_size NUMERIC -); --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_admin0_polygon (country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_admin0_polygon(username, orgname, country_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_admin1_polygon (admin1_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_admin1_polygon (admin1_name text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name, country_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point (city_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point (city_name text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, country_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point (city_name text ,admin1_name text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, admin1_name, country_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_polygon (postal_code text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_polygon (postal_code double precision ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_point (postal_code text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_point (postal_code double precision ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_ipaddress_point (ip_address text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_ipaddress_point(username, orgname, ip_address) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point (searches jsonb) -RETURNS SETOF cdb_dataservices_client.geocoding AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client.__cdb_bulk_geocode_street_point(username, orgname, searches); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_here_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_here_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_google_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_google_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_mapbox_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_tomtom_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocodio_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_geocodio_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapzen_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._cdb_mapzen_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_isodistance(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_isochrone(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_isochrone(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isochrone(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isochrone(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapzen_isochrone (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapzen_isochrone(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_isodistance(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isodistance(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isodistance(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapzen_isodistance (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapzen_isodistance(username, orgname, source, mode, range, options); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_route_point_to_point (origin public.geometry(Point, 4326) ,destination public.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; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'routing' THEN - RAISE EXCEPTION 'Routing permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT * 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 STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_route_with_waypoints (waypoints public.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; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'routing' THEN - RAISE EXCEPTION 'Routing permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT * FROM cdb_dataservices_client._cdb_route_with_waypoints(username, orgname, waypoints, mode, options, units) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_get_demographic_snapshot (geom public.geometry(Geometry, 4326) ,time_span text DEFAULT '2009 - 2013'::text ,geometry_level text DEFAULT NULL) -RETURNS json AS $$ -DECLARE - ret json; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_get_demographic_snapshot(username, orgname, geom, time_span, geometry_level) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_get_segment_snapshot (geom public.geometry(Geometry, 4326) ,geometry_level text DEFAULT NULL) -RETURNS json AS $$ -DECLARE - ret json; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_get_segment_snapshot(username, orgname, geom, geometry_level) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdemographicsnapshot (geom public.geometry(Geometry, 4326) ,time_span text DEFAULT NULL ,geometry_level text DEFAULT NULL) -RETURNS SETOF JSON AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdemographicsnapshot(username, orgname, geom, time_span, geometry_level); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getsegmentsnapshot (geom public.geometry(Geometry, 4326) ,geometry_level text DEFAULT NULL) -RETURNS SETOF JSON AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getsegmentsnapshot(username, orgname, geom, geometry_level); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundary (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getboundary(username, orgname, geom, boundary_id, time_span) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundaryid (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL) -RETURNS text AS $$ -DECLARE - ret text; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getboundaryid(username, orgname, geom, boundary_id, time_span) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundarybyid (geometry_id text ,boundary_id text ,time_span text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getboundarybyid(username, orgname, geometry_id, boundary_id, time_span) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundariesbygeometry (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getboundariesbygeometry(username, orgname, geom, boundary_id, time_span, overlap_type); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getboundariesbypointandradius (geom public.geometry(Geometry, 4326) ,radius numeric ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getboundariesbypointandradius(username, orgname, geom, radius, boundary_id, time_span, overlap_type); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getpointsbygeometry (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getpointsbygeometry(username, orgname, geom, boundary_id, time_span, overlap_type); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getpointsbypointandradius (geom public.geometry(Geometry, 4326) ,radius numeric ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getpointsbypointandradius(username, orgname, geom, radius, boundary_id, time_span, overlap_type); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getmeasure (geom public.Geometry ,measure_id text ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS numeric AS $$ -DECLARE - ret numeric; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getmeasure(username, orgname, geom, measure_id, normalize, boundary_id, time_span) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getmeasurebyid (geom_ref text ,measure_id text ,boundary_id text ,time_span text DEFAULT NULL) -RETURNS numeric AS $$ -DECLARE - ret numeric; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getmeasurebyid(username, orgname, geom_ref, measure_id, boundary_id, time_span) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdata (geomvals geomval[] ,params json ,merge boolean DEFAULT true) -RETURNS TABLE(id int, data json) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomvals, params, merge); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdata (geomrefs text[] ,params json) -RETURNS TABLE(id text, data json) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomrefs, params); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getmeta (geom_ref public.Geometry(Geometry, 4326) ,params json ,max_timespan_rank integer DEFAULT NULL ,max_score_rank integer DEFAULT NULL ,target_geoms integer DEFAULT NULL) -RETURNS json AS $$ -DECLARE - ret json; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_metadatavalidation (geom_extent public.Geometry(Geometry, 4326) ,geom_type text ,params json ,target_geoms integer DEFAULT NULL) -RETURNS TABLE(valid boolean, errors text[]) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_metadatavalidation(username, orgname, geom_extent, geom_type, params, target_geoms); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getcategory (geom public.Geometry ,category_id text ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS text AS $$ -DECLARE - ret text; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getcategory(username, orgname, geom, category_id, boundary_id, time_span) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getuscensusmeasure (geom public.Geometry ,name text ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS numeric AS $$ -DECLARE - ret numeric; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getuscensusmeasure(username, orgname, geom, name, normalize, boundary_id, time_span) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getuscensuscategory (geom public.Geometry ,name text ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS text AS $$ -DECLARE - ret text; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getuscensuscategory(username, orgname, geom, name, boundary_id, time_span) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getpopulation (geom public.Geometry ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS numeric AS $$ -DECLARE - ret numeric; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_getpopulation(username, orgname, geom, normalize, boundary_id, time_span) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_search (search_term text ,relevant_boundary text DEFAULT NULL) -RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_search(username, orgname, search_term, relevant_boundary); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailableboundaries (geom public.Geometry ,timespan text DEFAULT NULL) -RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailableboundaries(username, orgname, geom, timespan); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_dumpversion () -RETURNS text AS $$ -DECLARE - ret text; - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT cdb_dataservices_client._obs_dumpversion(username, orgname) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailablenumerators (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,denom_id text DEFAULT NULL ,geom_id text DEFAULT NULL ,timespan text DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailablenumerators(username, orgname, bounds, filter_tags, denom_id, geom_id, timespan); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getnumerators (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,section_tags text[] DEFAULT ARRAY[]::TEXT[] ,subsection_tags text[] DEFAULT ARRAY[]::TEXT[] ,other_tags text[] DEFAULT ARRAY[]::TEXT[] ,ids text[] DEFAULT ARRAY[]::TEXT[] ,name text DEFAULT NULL ,denom_id text DEFAULT '' ,geom_id text DEFAULT '' ,timespan text DEFAULT '') -RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client.__obs_getnumerators(username, orgname, bounds, section_tags, subsection_tags, other_tags, ids, name, denom_id, geom_id, timespan); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailabledenominators (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,geom_id text DEFAULT NULL ,timespan text DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_denominator AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailabledenominators(username, orgname, bounds, filter_tags, numer_id, geom_id, timespan); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailablegeometries (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,denom_id text DEFAULT NULL ,timespan text DEFAULT NULL ,number_geometries integer DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_geometry AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailablegeometries(username, orgname, bounds, filter_tags, numer_id, denom_id, timespan, number_geometries); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailabletimespans (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,denom_id text DEFAULT NULL ,geom_id text DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_timespan AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailabletimespans(username, orgname, bounds, filter_tags, numer_id, denom_id, geom_id); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_legacybuildermetadata (aggregate_type text DEFAULT NULL) -RETURNS TABLE(name text, subsection json) AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_legacybuildermetadata(username, orgname, aggregate_type); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_quota_info () -RETURNS SETOF service_quota_info AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_service_quota_info(username, orgname); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch () -RETURNS SETOF service_quota_info_batch AS $$ -DECLARE - - username text; - orgname text; - apikey_permissions json; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_service_quota_info_batch(username, orgname); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC) -RETURNS BOOLEAN AS $$ -DECLARE - ret BOOLEAN; - username text; - orgname text; - apikey_permissions json; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - - - -- 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_enough_quota(username, orgname, service, input_size) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_get_rate_limit (service text) -RETURNS json AS $$ -DECLARE - ret json; - username text; - orgname text; - apikey_permissions json; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - - - -- 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_service_get_rate_limit(username, orgname, service) INTO ret; RETURN ret; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_set_user_rate_limit (username text ,orgname text ,service text ,rate_limit json) -RETURNS void AS $$ -DECLARE - - - -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, p json); - -- 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; - - PERFORM cdb_dataservices_client._cdb_service_set_user_rate_limit(username, orgname, service, rate_limit); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_set_org_rate_limit (username text ,orgname text ,service text ,rate_limit json) -RETURNS void AS $$ -DECLARE - - - -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, p json); - -- 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; - - PERFORM cdb_dataservices_client._cdb_service_set_org_rate_limit(username, orgname, service, rate_limit); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Public dataservices API function --- --- These are the only ones with permissions to publicuser role --- and should also be the only ones with SECURITY DEFINER - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_set_server_rate_limit (username text ,orgname text ,service text ,rate_limit json) -RETURNS void AS $$ -DECLARE - - - -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, p json); - -- 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; - - PERFORM cdb_dataservices_client._cdb_service_set_server_rate_limit(username, orgname, service, rate_limit); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; -CREATE TYPE cdb_dataservices_client.ds_fdw_metadata as (schemaname text, tabname text, servername text); -CREATE TYPE cdb_dataservices_client.ds_return_metadata as (colnames text[], coltypes text[]); - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_PrepareTableOBS_GetMeasure( - output_table_name text, - params json -) RETURNS boolean AS $$ -DECLARE - username text; - user_db_role text; - orgname text; - user_schema text; - result boolean; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - - SELECT session_user INTO user_db_role; - - SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument'; - END IF; - - IF orgname IS NULL OR orgname = '' OR orgname = '""' THEN - user_schema := 'public'; - ELSE - user_schema := username; - END IF; - - SELECT cdb_dataservices_client.__DST_PrepareTableOBS_GetMeasure( - username, - orgname, - user_db_role, - user_schema, - output_table_name, - params - ) INTO result; - - RETURN result; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE - SET search_path = pg_temp; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_PopulateTableOBS_GetMeasure( - table_name text, - output_table_name text, - params json -) RETURNS boolean AS $$ -DECLARE - username text; - user_db_role text; - orgname text; - dbname text; - user_schema text; - result boolean; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - - SELECT session_user INTO user_db_role; - - SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument'; - END IF; - - IF orgname IS NULL OR orgname = '' OR orgname = '""' THEN - user_schema := 'public'; - ELSE - user_schema := username; - END IF; - - SELECT current_database() INTO dbname; - - SELECT cdb_dataservices_client.__DST_PopulateTableOBS_GetMeasure( - username, - orgname, - user_db_role, - user_schema, - dbname, - table_name, - output_table_name, - params - ) INTO result; - - RETURN result; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE - SET search_path = pg_temp; - - - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.__DST_PrepareTableOBS_GetMeasure( - username text, - orgname text, - user_db_role text, - user_schema text, - output_table_name text, - params json -) RETURNS boolean AS $$ - function_name = 'OBS_GetMeasure' - # Obtain return types for augmentation procedure - ds_return_metadata = plpy.execute("SELECT colnames, coltypes " - "FROM cdb_dataservices_client._DST_GetReturnMetadata({username}::text, {orgname}::text, {function_name}::text, {params}::json);" - .format( - username=plpy.quote_nullable(username), - orgname=plpy.quote_nullable(orgname), - function_name=plpy.quote_literal(function_name), - params=plpy.quote_literal(params) - ) - ) - if ds_return_metadata[0]["colnames"]: - colnames_arr = ds_return_metadata[0]["colnames"] - coltypes_arr = ds_return_metadata[0]["coltypes"] - else: - raise Exception('Error retrieving OBS_GetMeasure metadata') - - - # Prepare column and type strings required in the SQL queries - columns_with_types_arr = [colnames_arr[i] + ' ' + coltypes_arr[i] for i in range(0,len(colnames_arr))] - columns_with_types = ','.join(columns_with_types_arr) - - # Create a new table with the required columns - plpy.execute('CREATE TABLE "{schema}".{table_name} ( ' - 'cartodb_id int, the_geom public.geometry, {columns_with_types} ' - ');' - .format(schema=user_schema, table_name=output_table_name, columns_with_types=columns_with_types) - ) - - plpy.execute('ALTER TABLE "{schema}".{table_name} OWNER TO "{user}";' - .format(schema=user_schema, table_name=output_table_name, user=user_db_role) - ) - - return True -$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.__DST_PopulateTableOBS_GetMeasure( - username text, - orgname text, - user_db_role text, - user_schema text, - dbname text, - table_name text, - output_table_name text, - params json -) RETURNS boolean AS $$ - function_name = 'OBS_GetMeasure' - # Obtain return types for augmentation procedure - ds_return_metadata = plpy.execute( - "SELECT colnames, coltypes " - "FROM cdb_dataservices_client._DST_GetReturnMetadata({username}::text, {orgname}::text, {function_name}::text, {params}::json);" .format( - username=plpy.quote_nullable(username), - orgname=plpy.quote_nullable(orgname), - function_name=plpy.quote_literal(function_name), - params=plpy.quote_literal(params))) - - if ds_return_metadata[0]["colnames"]: - colnames_arr = ds_return_metadata[0]["colnames"] - coltypes_arr = ds_return_metadata[0]["coltypes"] - else: - raise Exception('Error retrieving OBS_GetMeasure metadata') - - # Prepare column and type strings required in the SQL queries - columns_with_types_arr = [ - colnames_arr[i] + - ' ' + - coltypes_arr[i] for i in range( - 0, - len(colnames_arr))] - columns_with_types = ','.join(columns_with_types_arr) - aliased_colname_list = ','.join( - ['result.' + name for name in colnames_arr]) - - # Instruct the OBS server side to establish a FDW - # The metadata is obtained as well in order to: - # - (a) be able to write the query to grab the actual data to be executed in the remote server via pl/proxy, - # - (b) be able to tell OBS to free resources when done. - ds_fdw_metadata = plpy.execute( - "SELECT schemaname, tabname, servername " - "FROM cdb_dataservices_client._DST_ConnectUserTable({username}::text, {orgname}::text, {user_db_role}::text, " - "{schema}::text, {dbname}::text, {table_name}::text);" .format( - username=plpy.quote_nullable(username), - orgname=plpy.quote_nullable(orgname), - user_db_role=plpy.quote_literal(user_db_role), - schema=plpy.quote_literal(user_schema), - dbname=plpy.quote_literal(dbname), - table_name=plpy.quote_literal(table_name))) - - if ds_fdw_metadata[0]["schemaname"]: - server_schema = ds_fdw_metadata[0]["schemaname"] - server_table_name = ds_fdw_metadata[0]["tabname"] - server_name = ds_fdw_metadata[0]["servername"] - else: - raise Exception('Error connecting dataset via FDW') - - # Create a new table with the required columns - plpy.execute( - 'INSERT INTO "{schema}".{analysis_table_name} ' - 'SELECT ut.cartodb_id, ut.the_geom, {colname_list} ' - 'FROM "{schema}".{table_name} ut ' - 'LEFT JOIN cdb_dataservices_client._DST_FetchJoinFdwTableData({username}::text, {orgname}::text, {server_schema}::text, {server_table_name}::text, ' - '{function_name}::text, {params}::json) ' - 'AS result ({columns_with_types}, cartodb_id int) ' - 'ON result.cartodb_id = ut.cartodb_id;' .format( - schema=user_schema, - analysis_table_name=output_table_name, - colname_list=aliased_colname_list, - table_name=table_name, - username=plpy.quote_nullable(username), - orgname=plpy.quote_nullable(orgname), - server_schema=plpy.quote_literal(server_schema), - server_table_name=plpy.quote_literal(server_table_name), - function_name=plpy.quote_literal(function_name), - params=plpy.quote_literal(params), - columns_with_types=columns_with_types)) - - # Wipe user FDW data from the server - wiped = plpy.execute( - "SELECT cdb_dataservices_client._DST_DisconnectUserTable({username}::text, {orgname}::text, {server_schema}::text, " - "{server_table_name}::text, {fdw_server}::text)" .format( - username=plpy.quote_nullable(username), - orgname=plpy.quote_nullable(orgname), - server_schema=plpy.quote_literal(server_schema), - server_table_name=plpy.quote_literal(server_table_name), - fdw_server=plpy.quote_literal(server_name))) - - return True -$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_ConnectUserTable( - username text, - orgname text, - user_db_role text, - user_schema text, - dbname text, - table_name text -)RETURNS cdb_dataservices_client.ds_fdw_metadata AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - TARGET cdb_dataservices_server._DST_ConnectUserTable; -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_GetReturnMetadata( - username text, - orgname text, - function_name text, - params json -) RETURNS cdb_dataservices_client.ds_return_metadata AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - TARGET cdb_dataservices_server._DST_GetReturnMetadata; -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_FetchJoinFdwTableData( - username text, - orgname text, - table_schema text, - table_name text, - function_name text, - params json -) RETURNS SETOF record AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - TARGET cdb_dataservices_server._DST_FetchJoinFdwTableData; -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._DST_DisconnectUserTable( - username text, - orgname text, - table_schema text, - table_name text, - server_name text -) RETURNS boolean AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - TARGET cdb_dataservices_server._DST_DisconnectUserTable; -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point (query text, - street_column text, city_column text default null, state_column text default null, country_column text default null, batch_size integer DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.geocoding AS $$ -DECLARE - query_row_count integer; - enough_quota boolean; - remaining_quota integer; - max_batch_size integer; - - cartodb_id_batch integer; - batches_n integer; - DEFAULT_BATCH_SIZE CONSTANT numeric := 100; - MAX_SAFE_BATCH_SIZE CONSTANT numeric := 5000; - - temp_table_name text; - username text; - orgname text; - apikey_permissions json; -BEGIN - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - SELECT csqi.monthly_quota - csqi.used_quota AS remaining_quota, csqi.max_batch_size - INTO remaining_quota, max_batch_size - FROM cdb_dataservices_client.cdb_service_quota_info_batch() csqi - WHERE service = 'hires_geocoder'; - RAISE DEBUG 'remaining_quota: %; max_batch_size: %', remaining_quota, max_batch_size; - - IF batch_size IS NULL THEN - batch_size := max_batch_size; - ELSIF batch_size > max_batch_size THEN - RAISE EXCEPTION 'batch_size must be lower than %', max_batch_size + 1; - END IF; - - IF batch_size > MAX_SAFE_BATCH_SIZE THEN - batch_size := MAX_SAFE_BATCH_SIZE; - END IF; - - EXECUTE format('SELECT count(1), ceil(count(1)::float/%s) FROM (%s) _x', batch_size, query) - INTO query_row_count, batches_n; - - RAISE DEBUG 'cdb_bulk_geocode_street_point --> query_row_count: %; query: %; country: %; state: %; city: %; street: %', - query_row_count, query, country_column, state_column, city_column, street_column; - SELECT cdb_dataservices_client.cdb_enough_quota('hires_geocoder', query_row_count) INTO enough_quota; - IF enough_quota IS NULL OR NOT enough_quota THEN - RAISE EXCEPTION 'Remaining quota: %. Estimated cost: %', remaining_quota, query_row_count; - END IF; - - RAISE DEBUG 'batches_n: %', batches_n; - - temp_table_name := 'bulk_geocode_street_' || md5(random()::text); - - EXECUTE format('CREATE TEMPORARY TABLE %s ' || - '(cartodb_id integer, the_geom public.geometry(Point,4326), metadata jsonb)', - temp_table_name); - - select - coalesce(street_column, ''''''), coalesce(city_column, ''''''), - coalesce(state_column, ''''''), coalesce(country_column, '''''') - into street_column, city_column, state_column, country_column; - - IF batches_n > 0 THEN - FOR cartodb_id_batch in 0..(batches_n - 1) - LOOP - EXECUTE format( - 'WITH geocoding_data as (' || - ' SELECT ' || - ' json_build_object(''id'', cartodb_id, ''address'', %s, ''city'', %s, ''state'', %s, ''country'', %s) as data , ' || - ' floor((row_number() over () - 1)::float/$1) as batch' || - ' FROM (%s) _x' || - ') ' || - 'INSERT INTO %s SELECT (cdb_dataservices_client._cdb_bulk_geocode_street_point(jsonb_agg(data))).* ' || - 'FROM geocoding_data ' || - 'WHERE batch = $2', street_column, city_column, state_column, country_column, query, temp_table_name) - USING batch_size, cartodb_id_batch; - - END LOOP; - END IF; - - RETURN QUERY EXECUTE 'SELECT * FROM ' || quote_ident(temp_table_name); -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin0_polygon_exception_safe (country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_admin0_polygon(username, orgname, country_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon_exception_safe (admin1_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon_exception_safe (admin1_name text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name, country_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point_exception_safe (city_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point_exception_safe (city_name text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, country_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point_exception_safe (city_name text ,admin1_name text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, admin1_name, country_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon_exception_safe (postal_code text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon_exception_safe (postal_code double precision ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point_exception_safe (postal_code text ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point_exception_safe (postal_code double precision ,country_name text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_ipaddress_point_exception_safe (ip_address text) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_ipaddress_point(username, orgname, ip_address) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point_exception_safe (searches jsonb) -RETURNS SETOF cdb_dataservices_client.geocoding AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client.__cdb_bulk_geocode_street_point(username, orgname, searches); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_here_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_here_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_google_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_google_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_mapbox_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_tomtom_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocodio_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_geocodio_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN - RAISE EXCEPTION 'Geocoding permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_mapzen_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_isodistance(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_isochrone(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_isochrone(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isochrone(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isochrone(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_isochrone_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapzen_isochrone(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_isodistance(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapbox_iso_isodistance(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isodistance(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_isodistance_exception_safe (source public.geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'isolines' THEN - RAISE EXCEPTION 'Isolines permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_mapzen_isodistance(username, orgname, source, mode, range, options); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_point_to_point_exception_safe (origin public.geometry(Point, 4326) ,destination public.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; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'routing' THEN - RAISE EXCEPTION 'Routing permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_with_waypoints_exception_safe (waypoints public.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; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'routing' THEN - RAISE EXCEPTION 'Routing permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT * FROM cdb_dataservices_client._cdb_route_with_waypoints(username, orgname, waypoints, mode, options, units) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_get_demographic_snapshot_exception_safe (geom public.geometry(Geometry, 4326) ,time_span text DEFAULT '2009 - 2013'::text ,geometry_level text DEFAULT NULL) -RETURNS json AS $$ -DECLARE - ret json; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_get_demographic_snapshot(username, orgname, geom, time_span, geometry_level) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_get_segment_snapshot_exception_safe (geom public.geometry(Geometry, 4326) ,geometry_level text DEFAULT NULL) -RETURNS json AS $$ -DECLARE - ret json; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_get_segment_snapshot(username, orgname, geom, geometry_level) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdemographicsnapshot_exception_safe (geom public.geometry(Geometry, 4326) ,time_span text DEFAULT NULL ,geometry_level text DEFAULT NULL) -RETURNS SETOF JSON AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdemographicsnapshot(username, orgname, geom, time_span, geometry_level); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getsegmentsnapshot_exception_safe (geom public.geometry(Geometry, 4326) ,geometry_level text DEFAULT NULL) -RETURNS SETOF JSON AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getsegmentsnapshot(username, orgname, geom, geometry_level); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundary_exception_safe (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getboundary(username, orgname, geom, boundary_id, time_span) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundaryid_exception_safe (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL) -RETURNS text AS $$ -DECLARE - ret text; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getboundaryid(username, orgname, geom, boundary_id, time_span) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundarybyid_exception_safe (geometry_id text ,boundary_id text ,time_span text DEFAULT NULL) -RETURNS public.Geometry AS $$ -DECLARE - ret public.Geometry; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getboundarybyid(username, orgname, geometry_id, boundary_id, time_span) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundariesbygeometry_exception_safe (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getboundariesbygeometry(username, orgname, geom, boundary_id, time_span, overlap_type); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundariesbypointandradius_exception_safe (geom public.geometry(Geometry, 4326) ,radius numeric ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getboundariesbypointandradius(username, orgname, geom, radius, boundary_id, time_span, overlap_type); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpointsbygeometry_exception_safe (geom public.geometry(Geometry, 4326) ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getpointsbygeometry(username, orgname, geom, boundary_id, time_span, overlap_type); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpointsbypointandradius_exception_safe (geom public.geometry(Geometry, 4326) ,radius numeric ,boundary_id text ,time_span text DEFAULT NULL ,overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getpointsbypointandradius(username, orgname, geom, radius, boundary_id, time_span, overlap_type); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeasure_exception_safe (geom public.Geometry ,measure_id text ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS numeric AS $$ -DECLARE - ret numeric; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getmeasure(username, orgname, geom, measure_id, normalize, boundary_id, time_span) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeasurebyid_exception_safe (geom_ref text ,measure_id text ,boundary_id text ,time_span text DEFAULT NULL) -RETURNS numeric AS $$ -DECLARE - ret numeric; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getmeasurebyid(username, orgname, geom_ref, measure_id, boundary_id, time_span) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata_exception_safe (geomvals geomval[] ,params json ,merge boolean DEFAULT true) -RETURNS TABLE(id int, data json) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomvals, params, merge); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata_exception_safe (geomrefs text[] ,params json) -RETURNS TABLE(id text, data json) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomrefs, params); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeta_exception_safe (geom_ref public.Geometry(Geometry, 4326) ,params json ,max_timespan_rank integer DEFAULT NULL ,max_score_rank integer DEFAULT NULL ,target_geoms integer DEFAULT NULL) -RETURNS json AS $$ -DECLARE - ret json; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_metadatavalidation_exception_safe (geom_extent public.Geometry(Geometry, 4326) ,geom_type text ,params json ,target_geoms integer DEFAULT NULL) -RETURNS TABLE(valid boolean, errors text[]) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_metadatavalidation(username, orgname, geom_extent, geom_type, params, target_geoms); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getcategory_exception_safe (geom public.Geometry ,category_id text ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS text AS $$ -DECLARE - ret text; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getcategory(username, orgname, geom, category_id, boundary_id, time_span) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getuscensusmeasure_exception_safe (geom public.Geometry ,name text ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS numeric AS $$ -DECLARE - ret numeric; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getuscensusmeasure(username, orgname, geom, name, normalize, boundary_id, time_span) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getuscensuscategory_exception_safe (geom public.Geometry ,name text ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS text AS $$ -DECLARE - ret text; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getuscensuscategory(username, orgname, geom, name, boundary_id, time_span) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpopulation_exception_safe (geom public.Geometry ,normalize text DEFAULT NULL ,boundary_id text DEFAULT NULL ,time_span text DEFAULT NULL) -RETURNS numeric AS $$ -DECLARE - ret numeric; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_getpopulation(username, orgname, geom, normalize, boundary_id, time_span) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_search_exception_safe (search_term text ,relevant_boundary text DEFAULT NULL) -RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_search(username, orgname, search_term, relevant_boundary); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailableboundaries_exception_safe (geom public.Geometry ,timespan text DEFAULT NULL) -RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailableboundaries(username, orgname, geom, timespan); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_dumpversion_exception_safe () -RETURNS text AS $$ -DECLARE - ret text; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._obs_dumpversion(username, orgname) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablenumerators_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,denom_id text DEFAULT NULL ,geom_id text DEFAULT NULL ,timespan text DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailablenumerators(username, orgname, bounds, filter_tags, denom_id, geom_id, timespan); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client.__obs_getnumerators_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,section_tags text[] DEFAULT ARRAY[]::TEXT[] ,subsection_tags text[] DEFAULT ARRAY[]::TEXT[] ,other_tags text[] DEFAULT ARRAY[]::TEXT[] ,ids text[] DEFAULT ARRAY[]::TEXT[] ,name text DEFAULT NULL ,denom_id text DEFAULT '' ,geom_id text DEFAULT '' ,timespan text DEFAULT '') -RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client.__obs_getnumerators(username, orgname, bounds, section_tags, subsection_tags, other_tags, ids, name, denom_id, geom_id, timespan); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabledenominators_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,geom_id text DEFAULT NULL ,timespan text DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_denominator AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailabledenominators(username, orgname, bounds, filter_tags, numer_id, geom_id, timespan); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablegeometries_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,denom_id text DEFAULT NULL ,timespan text DEFAULT NULL ,number_geometries integer DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_geometry AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailablegeometries(username, orgname, bounds, filter_tags, numer_id, denom_id, timespan, number_geometries); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabletimespans_exception_safe (bounds public.geometry(Geometry, 4326) DEFAULT NULL ,filter_tags text[] DEFAULT NULL ,numer_id text DEFAULT NULL ,denom_id text DEFAULT NULL ,geom_id text DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_timespan AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_getavailabletimespans(username, orgname, bounds, filter_tags, numer_id, denom_id, geom_id); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_legacybuildermetadata_exception_safe (aggregate_type text DEFAULT NULL) -RETURNS TABLE(name text, subsection json) AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'observatory' THEN - RAISE EXCEPTION 'Data Observatory permission denied'; - END IF; - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._obs_legacybuildermetadata(username, orgname, aggregate_type); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info_exception_safe () -RETURNS SETOF service_quota_info AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_service_quota_info(username, orgname); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info_batch_exception_safe () -RETURNS SETOF service_quota_info_batch AS $$ -DECLARE - - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_service_quota_info_batch(username, orgname); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_enough_quota_exception_safe (service TEXT ,input_size NUMERIC) -RETURNS BOOLEAN AS $$ -DECLARE - ret BOOLEAN; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_enough_quota(username, orgname, service, input_size) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_get_rate_limit_exception_safe (service text) -RETURNS json AS $$ -DECLARE - ret json; - username text; - orgname text; - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - apikey_permissions json; -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - - - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - SELECT cdb_dataservices_client._cdb_service_get_rate_limit(username, orgname, service) INTO ret; RETURN ret; - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - RETURN ret; - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_user_rate_limit_exception_safe (username text ,orgname text ,service text ,rate_limit json) -RETURNS void AS $$ -DECLARE - - - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - PERFORM cdb_dataservices_client._cdb_service_set_user_rate_limit(username, orgname, service, rate_limit); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_org_rate_limit_exception_safe (username text ,orgname text ,service text ,rate_limit json) -RETURNS void AS $$ -DECLARE - - - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - PERFORM cdb_dataservices_client._cdb_service_set_org_rate_limit(username, orgname, service, rate_limit); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; --- --- Exception-safe private DataServices API function --- - -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_server_rate_limit_exception_safe (username text ,orgname text ,service text ,rate_limit json) -RETURNS void AS $$ -DECLARE - - - _returned_sqlstate TEXT; - _message_text TEXT; - _pg_exception_context TEXT; - -BEGIN - IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN - RAISE EXCEPTION 'The api_key must be provided'; - END IF; - SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json); - -- JSON value stored "" is taken as literal - IF username IS NULL OR username = '' OR username = '""' THEN - RAISE EXCEPTION 'Username is a mandatory argument, check it out'; - END IF; - - - BEGIN - PERFORM cdb_dataservices_client._cdb_service_set_server_rate_limit(username, orgname, service, rate_limit); - EXCEPTION - WHEN OTHERS THEN - GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE, - _message_text = MESSAGE_TEXT, - _pg_exception_context = PG_EXCEPTION_CONTEXT; - RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context; - - END; -END; -$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE - SET search_path = pg_temp; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_admin0_polygon (username text, orgname text, country_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin0_polygon (username text, orgname text, country_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_admin0_polygon (username, orgname, country_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, orgname text, admin1_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, orgname text, admin1_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_admin1_polygon (username, orgname, admin1_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, orgname text, admin1_name text, country_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, orgname text, admin1_name text, country_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_admin1_polygon (username, orgname, admin1_name, country_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_namedplace_point (username, orgname, city_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text, country_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text, country_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_namedplace_point (username, orgname, city_name, country_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text, admin1_name text, country_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point (username text, orgname text, city_name text, admin1_name text, country_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_namedplace_point (username, orgname, city_name, admin1_name, country_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_polygon (username text, orgname text, postal_code text, country_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon (username text, orgname text, postal_code text, country_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon (username, orgname, postal_code, country_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_polygon (username text, orgname text, postal_code double precision, country_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon (username text, orgname text, postal_code double precision, country_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon (username, orgname, postal_code, country_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_point (username text, orgname text, postal_code text, country_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point (username text, orgname text, postal_code text, country_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_postalcode_point (username, orgname, postal_code, country_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_point (username text, orgname text, postal_code double precision, country_name text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point (username text, orgname text, postal_code double precision, country_name text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_postalcode_point (username, orgname, postal_code, country_name); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_ipaddress_point (username text, orgname text, ip_address text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_ipaddress_point (username text, orgname text, ip_address text) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_ipaddress_point (username, orgname, ip_address); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocode_street_point (username, orgname, searchtext, city, state_province, country); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client.__cdb_bulk_geocode_street_point (username text, orgname text, searches jsonb); -CREATE OR REPLACE FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point (username text, orgname text, searches jsonb) -RETURNS SETOF cdb_dataservices_client.geocoding AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server._cdb_bulk_geocode_street_point (username, orgname, searches); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_here_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_here_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_here_geocode_street_point (username, orgname, searchtext, city, state_province, country); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_google_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_google_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_google_geocode_street_point (username, orgname, searchtext, city, state_province, country); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_mapbox_geocode_street_point (username, orgname, searchtext, city, state_province, country); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_tomtom_geocode_street_point (username, orgname, searchtext, city, state_province, country); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocodio_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocodio_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_geocodio_geocode_street_point (username, orgname, searchtext, city, state_province, country); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapzen_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_mapzen_geocode_street_point (username, orgname, searchtext, city, state_province, country); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isodistance (username text, orgname text, source public.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, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isochrone (username text, orgname text, source public.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, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapzen_isochrone (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_isochrone (username text, orgname text, source public.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_mapzen_isochrone (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_iso_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[]) -RETURNS SETOF cdb_dataservices_client.isoline AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapzen_isodistance (username text, orgname text, source public.geometry(Geometry, 4326), mode text, range integer[], options text[]); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapzen_isodistance (username text, orgname text, source public.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_mapzen_isodistance (username, orgname, source, mode, range, options); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_route_point_to_point (username text, orgname text, origin public.geometry(Point, 4326), destination public.geometry(Point, 4326), mode text, options text[], units text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_point_to_point (username text, orgname text, origin public.geometry(Point, 4326), destination public.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, orgname, origin, destination, mode, options, units); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_route_with_waypoints (username text, orgname text, waypoints public.geometry(Point, 4326)[], mode text, options text[], units text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_with_waypoints (username text, orgname text, waypoints public.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_with_waypoints (username, orgname, waypoints, mode, options, units); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_get_demographic_snapshot (username text, orgname text, geom public.geometry(Geometry, 4326), time_span text, geometry_level text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_get_demographic_snapshot (username text, orgname text, geom public.geometry(Geometry, 4326), time_span text DEFAULT '2009 - 2013'::text, geometry_level text DEFAULT NULL) -RETURNS json AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_get_demographic_snapshot (username, orgname, geom, time_span, geometry_level); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_get_segment_snapshot (username text, orgname text, geom public.geometry(Geometry, 4326), geometry_level text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_get_segment_snapshot (username text, orgname text, geom public.geometry(Geometry, 4326), geometry_level text DEFAULT NULL) -RETURNS json AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_get_segment_snapshot (username, orgname, geom, geometry_level); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdemographicsnapshot (username text, orgname text, geom public.geometry(Geometry, 4326), time_span text, geometry_level text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdemographicsnapshot (username text, orgname text, geom public.geometry(Geometry, 4326), time_span text DEFAULT NULL, geometry_level text DEFAULT NULL) -RETURNS SETOF JSON AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getdemographicsnapshot (username, orgname, geom, time_span, geometry_level); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getsegmentsnapshot (username text, orgname text, geom public.geometry(Geometry, 4326), geometry_level text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getsegmentsnapshot (username text, orgname text, geom public.geometry(Geometry, 4326), geometry_level text DEFAULT NULL) -RETURNS SETOF JSON AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getsegmentsnapshot (username, orgname, geom, geometry_level); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundary (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundary (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text DEFAULT NULL) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getboundary (username, orgname, geom, boundary_id, time_span); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundaryid (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundaryid (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text DEFAULT NULL) -RETURNS text AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getboundaryid (username, orgname, geom, boundary_id, time_span); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundarybyid (username text, orgname text, geometry_id text, boundary_id text, time_span text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundarybyid (username text, orgname text, geometry_id text, boundary_id text, time_span text DEFAULT NULL) -RETURNS public.Geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getboundarybyid (username, orgname, geometry_id, boundary_id, time_span); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundariesbygeometry (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundariesbygeometry (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text DEFAULT NULL, overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getboundariesbygeometry (username, orgname, geom, boundary_id, time_span, overlap_type); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundariesbypointandradius (username text, orgname text, geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getboundariesbypointandradius (username text, orgname text, geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text DEFAULT NULL, overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getboundariesbypointandradius (username, orgname, geom, radius, boundary_id, time_span, overlap_type); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getpointsbygeometry (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpointsbygeometry (username text, orgname text, geom public.geometry(Geometry, 4326), boundary_id text, time_span text DEFAULT NULL, overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getpointsbygeometry (username, orgname, geom, boundary_id, time_span, overlap_type); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getpointsbypointandradius (username text, orgname text, geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpointsbypointandradius (username text, orgname text, geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text DEFAULT NULL, overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getpointsbypointandradius (username, orgname, geom, radius, boundary_id, time_span, overlap_type); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeasure (username text, orgname text, geom public.Geometry, measure_id text, normalize text, boundary_id text, time_span text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeasure (username text, orgname text, geom public.Geometry, measure_id text, normalize text DEFAULT NULL, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) -RETURNS numeric AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getmeasure (username, orgname, geom, measure_id, normalize, boundary_id, time_span); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeasurebyid (username text, orgname text, geom_ref text, measure_id text, boundary_id text, time_span text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeasurebyid (username text, orgname text, geom_ref text, measure_id text, boundary_id text, time_span text DEFAULT NULL) -RETURNS numeric AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getmeasurebyid (username, orgname, geom_ref, measure_id, boundary_id, time_span); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata (username text, orgname text, geomvals geomval[], params json, merge boolean); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata (username text, orgname text, geomvals geomval[], params json, merge boolean DEFAULT true) -RETURNS TABLE(id int, data json) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getdata (username, orgname, geomvals, params, merge); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata (username text, orgname text, geomrefs text[], params json); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata (username text, orgname text, geomrefs text[], params json) -RETURNS TABLE(id text, data json) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getdata (username, orgname, geomrefs, params); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeta (username text, orgname text, geom_ref public.Geometry(Geometry, 4326), params json, max_timespan_rank integer, max_score_rank integer, target_geoms integer); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeta (username text, orgname text, geom_ref public.Geometry(Geometry, 4326), params json, max_timespan_rank integer DEFAULT NULL, max_score_rank integer DEFAULT NULL, target_geoms integer DEFAULT NULL) -RETURNS json AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getmeta (username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_metadatavalidation (username text, orgname text, geom_extent public.Geometry(Geometry, 4326), geom_type text, params json, target_geoms integer); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_metadatavalidation (username text, orgname text, geom_extent public.Geometry(Geometry, 4326), geom_type text, params json, target_geoms integer DEFAULT NULL) -RETURNS TABLE(valid boolean, errors text[]) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_metadatavalidation (username, orgname, geom_extent, geom_type, params, target_geoms); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getcategory (username text, orgname text, geom public.Geometry, category_id text, boundary_id text, time_span text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getcategory (username text, orgname text, geom public.Geometry, category_id text, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) -RETURNS text AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getcategory (username, orgname, geom, category_id, boundary_id, time_span); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getuscensusmeasure (username text, orgname text, geom public.Geometry, name text, normalize text, boundary_id text, time_span text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getuscensusmeasure (username text, orgname text, geom public.Geometry, name text, normalize text DEFAULT NULL, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) -RETURNS numeric AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getuscensusmeasure (username, orgname, geom, name, normalize, boundary_id, time_span); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getuscensuscategory (username text, orgname text, geom public.Geometry, name text, boundary_id text, time_span text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getuscensuscategory (username text, orgname text, geom public.Geometry, name text, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) -RETURNS text AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getuscensuscategory (username, orgname, geom, name, boundary_id, time_span); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getpopulation (username text, orgname text, geom public.Geometry, normalize text, boundary_id text, time_span text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getpopulation (username text, orgname text, geom public.Geometry, normalize text DEFAULT NULL, boundary_id text DEFAULT NULL, time_span text DEFAULT NULL) -RETURNS numeric AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_getpopulation (username, orgname, geom, normalize, boundary_id, time_span); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_search (username text, orgname text, search_term text, relevant_boundary text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_search (username text, orgname text, search_term text, relevant_boundary text DEFAULT NULL) -RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_search (username, orgname, search_term, relevant_boundary); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailableboundaries (username text, orgname text, geom public.Geometry, timespan text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailableboundaries (username text, orgname text, geom public.Geometry, timespan text DEFAULT NULL) -RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getavailableboundaries (username, orgname, geom, timespan); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_dumpversion (username text, orgname text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_dumpversion (username text, orgname text) -RETURNS text AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.obs_dumpversion (username, orgname); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailablenumerators (username text, orgname text, bounds public.geometry(Geometry, 4326), filter_tags text[], denom_id text, geom_id text, timespan text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablenumerators (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, denom_id text DEFAULT NULL, geom_id text DEFAULT NULL, timespan text DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getavailablenumerators (username, orgname, bounds, filter_tags, denom_id, geom_id, timespan); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client.__obs_getnumerators (username text, orgname text, bounds public.geometry(Geometry, 4326), section_tags text[], subsection_tags text[], other_tags text[], ids text[], name text, denom_id text, geom_id text, timespan text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client.__obs_getnumerators (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, section_tags text[] DEFAULT ARRAY[]::TEXT[], subsection_tags text[] DEFAULT ARRAY[]::TEXT[], other_tags text[] DEFAULT ARRAY[]::TEXT[], ids text[] DEFAULT ARRAY[]::TEXT[], name text DEFAULT NULL, denom_id text DEFAULT '', geom_id text DEFAULT '', timespan text DEFAULT '') -RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server._obs_getnumerators (username, orgname, bounds, section_tags, subsection_tags, other_tags, ids, name, denom_id, geom_id, timespan); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailabledenominators (username text, orgname text, bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, geom_id text, timespan text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabledenominators (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, geom_id text DEFAULT NULL, timespan text DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_denominator AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getavailabledenominators (username, orgname, bounds, filter_tags, numer_id, geom_id, timespan); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailablegeometries (username text, orgname text, bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, timespan text, number_geometries integer); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablegeometries (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, denom_id text DEFAULT NULL, timespan text DEFAULT NULL, number_geometries integer DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_geometry AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getavailablegeometries (username, orgname, bounds, filter_tags, numer_id, denom_id, timespan, number_geometries); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailabletimespans (username text, orgname text, bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, geom_id text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabletimespans (username text, orgname text, bounds public.geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, denom_id text DEFAULT NULL, geom_id text DEFAULT NULL) -RETURNS SETOF cdb_dataservices_client.obs_meta_timespan AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_getavailabletimespans (username, orgname, bounds, filter_tags, numer_id, denom_id, geom_id); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_legacybuildermetadata (username text, orgname text, aggregate_type text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_legacybuildermetadata (username text, orgname text, aggregate_type text DEFAULT NULL) -RETURNS TABLE(name text, subsection json) AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.obs_legacybuildermetadata (username, orgname, aggregate_type); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_quota_info (username text, orgname text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info (username text, orgname text) -RETURNS SETOF service_quota_info AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_service_quota_info (username, orgname); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_quota_info_batch (username text, orgname text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info_batch (username text, orgname text) -RETURNS SETOF service_quota_info_batch AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT * FROM cdb_dataservices_server.cdb_service_quota_info_batch (username, orgname); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_enough_quota (username text, orgname text, service TEXT, input_size NUMERIC); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_enough_quota (username text, orgname text, service TEXT, input_size NUMERIC) -RETURNS BOOLEAN AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_enough_quota (username, orgname, service, input_size); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_get_rate_limit (username text, orgname text, service text); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_get_rate_limit (username text, orgname text, service text) -RETURNS json AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_service_get_rate_limit (username, orgname, service); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_set_user_rate_limit (username text, orgname text, service text, rate_limit json); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_user_rate_limit (username text, orgname text, service text, rate_limit json) -RETURNS void AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_service_set_user_rate_limit (username, orgname, service, rate_limit); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_set_org_rate_limit (username text, orgname text, service text, rate_limit json); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_org_rate_limit (username text, orgname text, service text, rate_limit json) -RETURNS void AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_service_set_org_rate_limit (username, orgname, service, rate_limit); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_set_server_rate_limit (username text, orgname text, service text, rate_limit json); -CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_set_server_rate_limit (username text, orgname text, service text, rate_limit json) -RETURNS void AS $$ - CONNECT cdb_dataservices_client._server_conn_str(); - - SELECT cdb_dataservices_server.cdb_service_set_server_rate_limit (username, orgname, service, rate_limit); - -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -CREATE OR REPLACE FUNCTION cdb_dataservices_client._OBS_PreCheck( - source_query text, - parameters json -) RETURNS boolean AS $$ -DECLARE - errors text[]; - validator_errors text[]; - validator_error text; - valid boolean; - geoms record; -BEGIN - errors := (ARRAY[])::TEXT[]; - FOR geoms IN EXECUTE format('SELECT ST_GeometryType(the_geom) as geom_type, - bool_and(st_isvalid(the_geom)) as valid, - avg(st_npoints(the_geom)) as avg_vertex, - ST_SetSRID(ST_Extent(the_geom), 4326) as extent, - count(*)::INT as numgeoms - FROM (%s) as _source - GROUP BY ST_GeometryType(the_geom)', source_query) - LOOP - IF geoms.geom_type NOT IN ('ST_Polygon', 'ST_MultiPolygon', 'ST_Point') THEN - errors := array_append(errors, format($data$'Geometry type %s not supported'$data$, geoms.geom_type)); - END IF; - - IF geoms.valid IS FALSE THEN - errors := array_append(errors, 'There are invalid geometries in the input data, please try to fix them'); - END IF; - - -- 1000 vertex for a geometry is a limit we have in the obs_getdata function. You can check here - -- https://github.com/CartoDB/observatory-extension/blob/1.6.0/src/pg/sql/41_observatory_augmentation.sql#L813 - IF geoms.avg_vertex > 1000 THEN - errors := array_append(errors, 'The average number of vertices per geometry is greater than 1000, please try to simplify them'); - END IF; - - -- OBS specific part - EXECUTE 'SELECT valid, errors - FROM cdb_dataservices_client.OBS_MetadataValidation($1, $2, $3, $4)' - INTO valid, validator_errors - USING geoms.extent, geoms.geom_type, parameters, geoms.numgeoms; - IF valid is FALSE THEN - FOR validator_error IN EXECUTE 'SELECT unnest($1)' USING validator_errors - LOOP - errors := array_append(errors, validator_error); - END LOOP; - END IF; - END LOOP; - - IF CARDINALITY(errors) > 0 THEN - RAISE EXCEPTION '%', errors; - END IF; - - RETURN TRUE; -END; -$$ LANGUAGE 'plpgsql' VOLATILE PARALLEL UNSAFE; --- 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_admin0_polygon_exception_safe(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_exception_safe(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_admin1_polygon_exception_safe(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_exception_safe(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_exception_safe(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_namedplace_point_exception_safe(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_polygon_exception_safe(postal_code text, country_name text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_polygon(postal_code double precision, country_name text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon_exception_safe(postal_code double precision, 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_postalcode_point_exception_safe(postal_code text, country_name text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_point(postal_code double precision, country_name text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point_exception_safe(postal_code double precision, 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_ipaddress_point_exception_safe(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_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point(searches jsonb) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point_exception_safe(searches jsonb ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_here_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_here_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_google_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_google_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocodio_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_geocodio_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapzen_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapzen_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapzen_isochrone(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapzen_isochrone_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_iso_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_iso_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapzen_isodistance(source public.geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapzen_isodistance_exception_safe(source public.geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_route_point_to_point(origin public.geometry(Point, 4326), destination public.geometry(Point, 4326), mode text, options text[], units text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_route_point_to_point_exception_safe(origin public.geometry(Point, 4326), destination public.geometry(Point, 4326), mode text, options text[], units text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_route_with_waypoints(waypoints public.geometry(Point, 4326)[], mode text, options text[], units text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_route_with_waypoints_exception_safe(waypoints public.geometry(Point, 4326)[], mode text, options text[], units text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_get_demographic_snapshot(geom public.geometry(Geometry, 4326), time_span text, geometry_level text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_get_demographic_snapshot_exception_safe(geom public.geometry(Geometry, 4326), time_span text, geometry_level text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_get_segment_snapshot(geom public.geometry(Geometry, 4326), geometry_level text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_get_segment_snapshot_exception_safe(geom public.geometry(Geometry, 4326), geometry_level text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getdemographicsnapshot(geom public.geometry(Geometry, 4326), time_span text, geometry_level text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getdemographicsnapshot_exception_safe(geom public.geometry(Geometry, 4326), time_span text, geometry_level text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getsegmentsnapshot(geom public.geometry(Geometry, 4326), geometry_level text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getsegmentsnapshot_exception_safe(geom public.geometry(Geometry, 4326), geometry_level text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundary(geom public.geometry(Geometry, 4326), boundary_id text, time_span text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundary_exception_safe(geom public.geometry(Geometry, 4326), boundary_id text, time_span text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundaryid(geom public.geometry(Geometry, 4326), boundary_id text, time_span text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundaryid_exception_safe(geom public.geometry(Geometry, 4326), boundary_id text, time_span text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundarybyid(geometry_id text, boundary_id text, time_span text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundarybyid_exception_safe(geometry_id text, boundary_id text, time_span text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundariesbygeometry(geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundariesbygeometry_exception_safe(geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getboundariesbypointandradius(geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getboundariesbypointandradius_exception_safe(geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getpointsbygeometry(geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getpointsbygeometry_exception_safe(geom public.geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getpointsbypointandradius(geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getpointsbypointandradius_exception_safe(geom public.geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getmeasure(geom public.Geometry, measure_id text, normalize text, boundary_id text, time_span text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getmeasure_exception_safe(geom public.Geometry, measure_id text, normalize text, boundary_id text, time_span text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getmeasurebyid(geom_ref text, measure_id text, boundary_id text, time_span text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getmeasurebyid_exception_safe(geom_ref text, measure_id text, boundary_id text, time_span text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getdata(geomvals geomval[], params json, merge boolean) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getdata_exception_safe(geomvals geomval[], params json, merge boolean ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getdata(geomrefs text[], params json) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getdata_exception_safe(geomrefs text[], params json ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getmeta(geom_ref public.Geometry(Geometry, 4326), params json, max_timespan_rank integer, max_score_rank integer, target_geoms integer) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getmeta_exception_safe(geom_ref public.Geometry(Geometry, 4326), params json, max_timespan_rank integer, max_score_rank integer, target_geoms integer ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_metadatavalidation(geom_extent public.Geometry(Geometry, 4326), geom_type text, params json, target_geoms integer) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_metadatavalidation_exception_safe(geom_extent public.Geometry(Geometry, 4326), geom_type text, params json, target_geoms integer ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getcategory(geom public.Geometry, category_id text, boundary_id text, time_span text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getcategory_exception_safe(geom public.Geometry, category_id text, boundary_id text, time_span text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getuscensusmeasure(geom public.Geometry, name text, normalize text, boundary_id text, time_span text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getuscensusmeasure_exception_safe(geom public.Geometry, name text, normalize text, boundary_id text, time_span text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getuscensuscategory(geom public.Geometry, name text, boundary_id text, time_span text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getuscensuscategory_exception_safe(geom public.Geometry, name text, boundary_id text, time_span text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getpopulation(geom public.Geometry, normalize text, boundary_id text, time_span text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getpopulation_exception_safe(geom public.Geometry, normalize text, boundary_id text, time_span text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_search(search_term text, relevant_boundary text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_search_exception_safe(search_term text, relevant_boundary text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailableboundaries(geom public.Geometry, timespan text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailableboundaries_exception_safe(geom public.Geometry, timespan text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_dumpversion() TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_dumpversion_exception_safe( ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailablenumerators(bounds public.geometry(Geometry, 4326), filter_tags text[], denom_id text, geom_id text, timespan text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailablenumerators_exception_safe(bounds public.geometry(Geometry, 4326), filter_tags text[], denom_id text, geom_id text, timespan text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getnumerators(bounds public.geometry(Geometry, 4326), section_tags text[], subsection_tags text[], other_tags text[], ids text[], name text, denom_id text, geom_id text, timespan text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.__obs_getnumerators_exception_safe(bounds public.geometry(Geometry, 4326), section_tags text[], subsection_tags text[], other_tags text[], ids text[], name text, denom_id text, geom_id text, timespan text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailabledenominators(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, geom_id text, timespan text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailabledenominators_exception_safe(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, geom_id text, timespan text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailablegeometries(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, timespan text, number_geometries integer) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailablegeometries_exception_safe(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, timespan text, number_geometries integer ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailabletimespans(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, geom_id text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_getavailabletimespans_exception_safe(bounds public.geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, geom_id text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_legacybuildermetadata(aggregate_type text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._obs_legacybuildermetadata_exception_safe(aggregate_type text ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_service_quota_info() TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_service_quota_info_exception_safe( ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch() TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_service_quota_info_batch_exception_safe( ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_enough_quota(service TEXT, input_size NUMERIC) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_enough_quota_exception_safe(service TEXT, input_size NUMERIC ) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_service_get_rate_limit(service text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_service_get_rate_limit_exception_safe(service text ) TO publicuser; - - - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PrepareTableOBS_GetMeasure(output_table_name text, params json) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PopulateTableOBS_GetMeasure(table_name text, output_table_name text, params json) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client._OBS_PreCheck(source_query text, params JSON) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point(query text, street_column text, city_column text, state_column text, country_column text, batch_size integer) TO publicuser; - -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_count_estimate(query text) TO publicuser; -GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_jsonb_array_casttext(jsonb) TO publicuser; diff --git a/client/cdb_dataservices_client.control b/client/cdb_dataservices_client.control index ebf1daf..395c212 100644 --- a/client/cdb_dataservices_client.control +++ b/client/cdb_dataservices_client.control @@ -1,5 +1,5 @@ comment = 'CartoDB dataservices client API extension' -default_version = '0.29.0' +default_version = '0.28.0' requires = 'plproxy, cartodb' superuser = true schema = cdb_dataservices_client diff --git a/client/renderer/interface.yaml b/client/renderer/interface.yaml index 60656d5..22585c0 100644 --- a/client/renderer/interface.yaml +++ b/client/renderer/interface.yaml @@ -221,19 +221,6 @@ - { name: range, type: "integer[]" } - { name: options, type: "text[]", default: 'ARRAY[]::text[]' } -- name: cdb_mapbox_iso_isochrone - return_type: SETOF cdb_dataservices_client.isoline - multi_row: true - multi_field: true - requires_permission: true - permission_name: isolines - permission_error: Isolines permission denied - params: - - { name: source, type: "public.geometry(Geometry, 4326)" } - - { name: mode, type: text } - - { name: range, type: "integer[]" } - - { name: options, type: "text[]", default: 'ARRAY[]::text[]' } - - name: cdb_tomtom_isochrone return_type: SETOF cdb_dataservices_client.isoline multi_row: true @@ -273,19 +260,6 @@ - { name: range, type: "integer[]" } - { name: options, type: "text[]", default: 'ARRAY[]::text[]' } -- name: cdb_mapbox_iso_isodistance - return_type: SETOF cdb_dataservices_client.isoline - multi_row: true - multi_field: true - requires_permission: true - permission_name: isolines - permission_error: Isolines permission denied - params: - - { name: source, type: "public.geometry(Geometry, 4326)" } - - { name: mode, type: text } - - { name: range, type: "integer[]" } - - { name: options, type: "text[]", default: 'ARRAY[]::text[]' } - - name: cdb_tomtom_isodistance return_type: SETOF cdb_dataservices_client.isoline multi_row: true From 822c574b5c3fb935898100ccc6b9557b03c6e4e6 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Tue, 11 Feb 2020 10:00:27 +0100 Subject: [PATCH 15/20] Deleted old mapbox isolines implementation --- .../cartodb_services/mapbox/__init__.py | 2 - .../cartodb_services/mapbox/isolines.py | 241 ++++++++---------- .../cartodb_services/mapbox/matrix_client.py | 92 ------- .../cartodb_services/mapbox/true_isolines.py | 154 ----------- .../cartodb_services/mapbox/types.py | 1 - .../cartodb_services/metrics/config.py | 81 ++---- .../cartodb_services/metrics/user.py | 2 - .../service/mapbox_isolines_config.py | 4 +- .../service/mapbox_true_isolines_config.py | 123 --------- .../test/metrics/test_config.py | 4 +- .../cartodb_services/test/test_helper.py | 3 +- .../test/test_mapboxisoline.py | 19 +- .../test/test_mapboxmatrix.py | 58 ----- .../test/test_mapboxtrueisoline.py | 42 --- .../test/test_quota_service.py | 17 -- 15 files changed, 138 insertions(+), 705 deletions(-) delete mode 100644 server/lib/python/cartodb_services/cartodb_services/mapbox/matrix_client.py delete mode 100644 server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py delete mode 100644 server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py delete mode 100644 server/lib/python/cartodb_services/test/test_mapboxmatrix.py delete mode 100644 server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/__init__.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/__init__.py index 5709f66..a7afcc6 100644 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/__init__.py +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/__init__.py @@ -2,5 +2,3 @@ from routing import MapboxRouting, MapboxRoutingResponse from geocoder import MapboxGeocoder from bulk_geocoder import MapboxBulkGeocoder from isolines import MapboxIsolines, MapboxIsochronesResponse -from true_isolines import MapboxTrueIsolines, MapboxTrueIsochronesResponse -from matrix_client import MapboxMatrixClient diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/isolines.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/isolines.py index 4d6563f..f3056e7 100644 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/isolines.py +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/isolines.py @@ -1,171 +1,142 @@ -''' -Python implementation for Mapbox services based isolines. -Uses the Mapbox Time Matrix service. -''' - import json +import requests +from uritemplate import URITemplate + +from cartodb_services.tools.exceptions import ServiceException +from cartodb_services.tools.qps import qps_retry from cartodb_services.tools import Coordinate -from cartodb_services.tools.spherical import (get_angles, - calculate_dest_location) -from cartodb_services.mapbox.matrix_client import (validate_profile, - DEFAULT_PROFILE, - PROFILE_WALKING, - PROFILE_DRIVING, - PROFILE_CYCLING, - ENTRY_DURATIONS, - ENTRY_DESTINATIONS, - ENTRY_LOCATION) + +BASEURI = ('https://api.mapbox.com/isochrone/v1/mapbox/{profile}/{coordinates}?contours_minutes={contours_minutes}&access_token={apikey}') + +PROFILE_DRIVING = 'driving' +PROFILE_CYCLING = 'cycling' +PROFILE_WALKING = 'walking' +DEFAULT_PROFILE = PROFILE_DRIVING + +MAX_TIME_RANGE = 60 * 60 # The maximum time that can be specified is 60 minutes. + # https://docs.mapbox.com/api/navigation/#retrieve-isochrones-around-a-location MAX_SPEEDS = { PROFILE_WALKING: 3.3333333, # In m/s, assuming 12km/h walking speed PROFILE_CYCLING: 16.67, # In m/s, assuming 60km/h max speed - PROFILE_DRIVING: 41.67 # In m/s, assuming 140km/h max speed + PROFILE_DRIVING: 38.89 # In m/s, assuming 140km/h max speed } -DEFAULT_NUM_ANGLES = 24 -DEFAULT_MAX_ITERS = 5 -DEFAULT_TOLERANCE = 0.1 +VALID_PROFILES = [PROFILE_DRIVING, + PROFILE_CYCLING, + PROFILE_WALKING] -MATRIX_NUM_ANGLES = DEFAULT_NUM_ANGLES -MATRIX_MAX_ITERS = DEFAULT_MAX_ITERS -MATRIX_TOLERANCE = DEFAULT_TOLERANCE - -UNIT_FACTOR_ISOCHRONE = 1.0 -UNIT_FACTOR_ISODISTANCE = 1000.0 -DEFAULT_UNIT_FACTOR = UNIT_FACTOR_ISOCHRONE +ENTRY_FEATURES = 'features' +ENTRY_GEOMETRY = 'geometry' +ENTRY_COORDINATES = 'coordinates' class MapboxIsolines(): ''' - Python wrapper for Mapbox services based isolines. + Python wrapper for Mapbox based isolines. ''' - def __init__(self, matrix_client, logger, service_params=None): + def __init__(self, apikey, logger, service_params=None): service_params = service_params or {} - self._matrix_client = matrix_client + self._apikey = apikey self._logger = logger - def _calculate_matrix_cost(self, origin, targets, isorange, - profile=DEFAULT_PROFILE, - unit_factor=UNIT_FACTOR_ISOCHRONE, - number_of_angles=MATRIX_NUM_ANGLES): - response = self._matrix_client.matrix([origin] + targets, - profile) + def _uri(self, origin, time_range, profile=DEFAULT_PROFILE): + uri = URITemplate(BASEURI).expand(apikey=self._apikey, + coordinates=origin, + contours_minutes=time_range, + profile=profile) + return uri + + def _validate_profile(self, profile): + if profile not in VALID_PROFILES: + raise ValueError('{profile} is not a valid profile. ' + 'Valid profiles are: {valid_profiles}'.format( + profile=profile, + valid_profiles=', '.join( + [x for x in VALID_PROFILES]))) + + def _validate_time_ranges(self, time_ranges): + for time_range in time_ranges: + if time_range > MAX_TIME_RANGE: + raise ValueError('Cannot query time ranges greater than {max_time_range} seconds'.format( + max_time_range=MAX_TIME_RANGE)) + + def _parse_coordinates(self, boundary): + coordinates = boundary.get(ENTRY_COORDINATES, []) + return [Coordinate(c[0], c[1]) for c in coordinates] + + def _parse_isochrone_service(self, response): json_response = json.loads(response) - if not json_response: - return [] - costs = [None] * number_of_angles - destinations = [None] * number_of_angles + coordinates = [] + if json_response: + for feature in json_response[ENTRY_FEATURES]: + geometry = feature[ENTRY_GEOMETRY] + coordinates.append(self._parse_coordinates(geometry)) - for idx, cost in enumerate(json_response[ENTRY_DURATIONS][0][1:]): - if cost: - costs[idx] = cost * unit_factor + return coordinates + + @qps_retry(qps=5, provider='mapbox') + def _calculate_isoline(self, origin, time_ranges, + profile=DEFAULT_PROFILE): + self._validate_time_ranges(time_ranges) + + origin = '{lon},{lat}'.format(lat=origin.latitude, + lon=origin.longitude) + + time_ranges.sort() + time_ranges_seconds = ','.join([str(round(t/60)) for t in time_ranges]) + + uri = self._uri(origin, time_ranges_seconds, profile) + + try: + response = requests.get(uri) + + if response.status_code == requests.codes.ok: + isolines = [] + coordinates = self._parse_isochrone_service(response.text) + for t, c in zip(time_ranges, coordinates): + isolines.append(MapboxIsochronesResponse(c, t)) + + return isolines + elif response.status_code == requests.codes.bad_request: + return [] + elif response.status_code == requests.codes.unprocessable_entity: + return [] else: - costs[idx] = isorange - - for idx, destination in enumerate(json_response[ENTRY_DESTINATIONS][1:]): - destinations[idx] = Coordinate(destination[ENTRY_LOCATION][0], - destination[ENTRY_LOCATION][1]) - - return costs, destinations + raise ServiceException(response.status_code, response) + except requests.Timeout as te: + # In case of timeout we want to stop the job because the server + # could be down + self._logger.error('Timeout connecting to Mapbox isochrone service', + te) + raise ServiceException('Error getting isochrone data from Mapbox', + None) + except requests.ConnectionError as ce: + # Don't raise the exception to continue with the geocoding job + self._logger.error('Error connecting to Mapbox isochrone service', + exception=ce) + return [] def calculate_isochrone(self, origin, time_ranges, profile=DEFAULT_PROFILE): - validate_profile(profile) + self._validate_profile(profile) - max_speed = MAX_SPEEDS[profile] - - isochrones = [] - for time_range in time_ranges: - upper_rmax = max_speed * time_range # an upper bound for the radius - - coordinates = self.calculate_isoline(origin=origin, - isorange=time_range, - upper_rmax=upper_rmax, - cost_method=self._calculate_matrix_cost, - profile=profile, - unit_factor=UNIT_FACTOR_ISOCHRONE, - number_of_angles=MATRIX_NUM_ANGLES, - max_iterations=MATRIX_MAX_ITERS, - tolerance=MATRIX_TOLERANCE) - isochrones.append(MapboxIsochronesResponse(coordinates, - time_range)) - return isochrones + return self._calculate_isoline(origin=origin, + time_ranges=time_ranges, + profile=profile) def calculate_isodistance(self, origin, distance_range, profile=DEFAULT_PROFILE): - validate_profile(profile) + self._validate_profile(profile) max_speed = MAX_SPEEDS[profile] time_range = distance_range / max_speed - return self.calculate_isochrone(origin=origin, - time_ranges=[time_range], - profile=profile)[0].coordinates - - def calculate_isoline(self, origin, isorange, upper_rmax, - cost_method=_calculate_matrix_cost, - profile=DEFAULT_PROFILE, - unit_factor=DEFAULT_UNIT_FACTOR, - number_of_angles=DEFAULT_NUM_ANGLES, - max_iterations=DEFAULT_MAX_ITERS, - tolerance=DEFAULT_TOLERANCE): - # Formally, a solution is an array of {angle, radius, lat, lon, cost} - # with cardinality number_of_angles - # we're looking for a solution in which - # abs(cost - isorange) / isorange <= TOLERANCE - - # Initial setup - angles = get_angles(number_of_angles) - rmax = [upper_rmax] * number_of_angles - rmin = [0.0] * number_of_angles - location_estimates = [calculate_dest_location(origin, a, - upper_rmax / 2.0) - for a in angles] - - # Iterate to refine the first solution - for i in xrange(0, max_iterations): - # Calculate the "actual" cost for each location estimate. - # NOTE: sometimes it cannot calculate the cost and returns None. - # Just assume isorange and stop the calculations there - - costs, destinations = cost_method(origin=origin, - targets=location_estimates, - isorange=isorange, - profile=profile, - unit_factor=unit_factor, - number_of_angles=number_of_angles) - - if not costs: - continue - - errors = [(cost - isorange) / float(isorange) for cost in costs] - max_abs_error = max([abs(e) for e in errors]) - if max_abs_error <= tolerance: - # good enough, stop there - break - - # let's refine the solution, binary search - for j in xrange(0, number_of_angles): - - if abs(errors[j]) > tolerance: - if errors[j] > 0: - rmax[j] = (rmax[j] + rmin[j]) / 2.0 - else: - rmin[j] = (rmax[j] + rmin[j]) / 2.0 - - location_estimates[j] = calculate_dest_location(origin, - angles[j], - (rmax[j] + rmin[j]) / 2.0) - - # delete points that got None - location_estimates_filtered = [] - for i, c in enumerate(costs): - if c != isorange and c < isorange * (1 + tolerance): - location_estimates_filtered.append(destinations[i]) - - return location_estimates_filtered + return self._calculate_isoline(origin=origin, + time_ranges=[time_range], + profile=profile)[0].coordinates class MapboxIsochronesResponse: diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/matrix_client.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/matrix_client.py deleted file mode 100644 index fd4cf1f..0000000 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/matrix_client.py +++ /dev/null @@ -1,92 +0,0 @@ -''' -Python client for the Mapbox Time Matrix service. -''' - -import requests -from cartodb_services.metrics import Traceable -from cartodb_services.tools.coordinates import (validate_coordinates, - marshall_coordinates) -from cartodb_services.tools.exceptions import ServiceException -from cartodb_services.tools.qps import qps_retry - -BASEURI = ('https://api.mapbox.com/directions-matrix/v1/mapbox/{profile}/' - '{coordinates}' - '?access_token={token}' - '&sources=0' # Set the first coordinate as source... - '&destinations=all') # ...and the rest as destinations - -NUM_COORDINATES_MIN = 2 # https://www.mapbox.com/api-documentation/#matrix -NUM_COORDINATES_MAX = 25 # https://www.mapbox.com/api-documentation/#matrix - -PROFILE_DRIVING_TRAFFIC = 'driving-traffic' -PROFILE_DRIVING = 'driving' -PROFILE_CYCLING = 'cycling' -PROFILE_WALKING = 'walking' -DEFAULT_PROFILE = PROFILE_DRIVING - -VALID_PROFILES = [PROFILE_DRIVING_TRAFFIC, - PROFILE_DRIVING, - PROFILE_CYCLING, - PROFILE_WALKING] - -ENTRY_DURATIONS = 'durations' -ENTRY_DESTINATIONS = 'destinations' -ENTRY_LOCATION = 'location' - - -def validate_profile(profile): - if profile not in VALID_PROFILES: - raise ValueError('{profile} is not a valid profile. ' - 'Valid profiles are: {valid_profiles}'.format( - profile=profile, - valid_profiles=', '.join( - [x for x in VALID_PROFILES]))) - - -class MapboxMatrixClient(Traceable): - ''' - Python wrapper for the Mapbox Time Matrix service. - ''' - - def __init__(self, token, logger, service_params=None): - service_params = service_params or {} - self._token = token - self._logger = logger - - def _uri(self, coordinates, profile=DEFAULT_PROFILE): - return BASEURI.format(profile=profile, coordinates=coordinates, - token=self._token) - - @qps_retry(qps=1) - def matrix(self, coordinates, profile=DEFAULT_PROFILE): - validate_profile(profile) - validate_coordinates(coordinates, - NUM_COORDINATES_MIN, NUM_COORDINATES_MAX) - - coords = marshall_coordinates(coordinates) - - uri = self._uri(coords, profile) - - try: - response = requests.get(uri) - - if response.status_code == requests.codes.ok: - return response.text - elif response.status_code == requests.codes.bad_request: - return '{}' - elif response.status_code == requests.codes.unprocessable_entity: - return '{}' - else: - raise ServiceException(response.status_code, response) - except requests.Timeout as te: - # In case of timeout we want to stop the job because the server - # could be down - self._logger.error('Timeout connecting to Mapbox matrix service', - te) - raise ServiceException('Error getting matrix data from Mapbox', - None) - except requests.ConnectionError as ce: - # Don't raise the exception to continue with the geocoding job - self._logger.error('Error connecting to Mapbox matrix service', - exception=ce) - return '{}' diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py deleted file mode 100644 index 89208f1..0000000 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/true_isolines.py +++ /dev/null @@ -1,154 +0,0 @@ -import json -import requests -from uritemplate import URITemplate - -from cartodb_services.tools.exceptions import ServiceException -from cartodb_services.tools.qps import qps_retry -from cartodb_services.tools import Coordinate - -BASEURI = ('https://api.mapbox.com/isochrone/v1/mapbox/{profile}/{coordinates}?contours_minutes={contours_minutes}&access_token={apikey}') - -PROFILE_DRIVING = 'driving' -PROFILE_CYCLING = 'cycling' -PROFILE_WALKING = 'walking' -DEFAULT_PROFILE = PROFILE_DRIVING - -MAX_TIME_RANGE = 60 * 60 # The maximum time that can be specified is 60 minutes. - # https://docs.mapbox.com/api/navigation/#retrieve-isochrones-around-a-location - -MAX_SPEEDS = { - PROFILE_WALKING: 3.3333333, # In m/s, assuming 12km/h walking speed - PROFILE_CYCLING: 16.67, # In m/s, assuming 60km/h max speed - PROFILE_DRIVING: 38.89 # In m/s, assuming 140km/h max speed -} - -VALID_PROFILES = [PROFILE_DRIVING, - PROFILE_CYCLING, - PROFILE_WALKING] - -ENTRY_FEATURES = 'features' -ENTRY_GEOMETRY = 'geometry' -ENTRY_COORDINATES = 'coordinates' - - -class MapboxTrueIsolines(): - ''' - Python wrapper for Mapbox based isolines. - ''' - - def __init__(self, apikey, logger, service_params=None): - service_params = service_params or {} - self._apikey = apikey - self._logger = logger - - def _uri(self, origin, time_range, profile=DEFAULT_PROFILE): - uri = URITemplate(BASEURI).expand(apikey=self._apikey, - coordinates=origin, - contours_minutes=time_range, - profile=profile) - return uri - - def _validate_profile(self, profile): - if profile not in VALID_PROFILES: - raise ValueError('{profile} is not a valid profile. ' - 'Valid profiles are: {valid_profiles}'.format( - profile=profile, - valid_profiles=', '.join( - [x for x in VALID_PROFILES]))) - - def _validate_time_ranges(self, time_ranges): - for time_range in time_ranges: - if time_range > MAX_TIME_RANGE: - raise ValueError('Cannot query time ranges greater than {max_time_range} seconds'.format( - max_time_range=MAX_TIME_RANGE)) - - def _parse_coordinates(self, boundary): - coordinates = boundary.get(ENTRY_COORDINATES, []) - return [Coordinate(c[0], c[1]) for c in coordinates] - - def _parse_isochrone_service(self, response): - json_response = json.loads(response) - - coordinates = [] - if json_response: - for feature in json_response[ENTRY_FEATURES]: - geometry = feature[ENTRY_GEOMETRY] - coordinates.append(self._parse_coordinates(geometry)) - - return coordinates - - @qps_retry(qps=5, provider='mapbox_iso') - def _calculate_isoline(self, origin, time_ranges, - profile=DEFAULT_PROFILE): - self._validate_time_ranges(time_ranges) - - origin = '{lon},{lat}'.format(lat=origin.latitude, - lon=origin.longitude) - - time_ranges.sort() - time_ranges_seconds = ','.join([str(round(t/60)) for t in time_ranges]) - - uri = self._uri(origin, time_ranges_seconds, profile) - - try: - response = requests.get(uri) - - if response.status_code == requests.codes.ok: - isolines = [] - coordinates = self._parse_isochrone_service(response.text) - for t, c in zip(time_ranges, coordinates): - isolines.append(MapboxTrueIsochronesResponse(c, t)) - - return isolines - elif response.status_code == requests.codes.bad_request: - return [] - elif response.status_code == requests.codes.unprocessable_entity: - return [] - else: - raise ServiceException(response.status_code, response) - except requests.Timeout as te: - # In case of timeout we want to stop the job because the server - # could be down - self._logger.error('Timeout connecting to Mapbox isochrone service', - te) - raise ServiceException('Error getting isochrone data from Mapbox', - None) - except requests.ConnectionError as ce: - # Don't raise the exception to continue with the geocoding job - self._logger.error('Error connecting to Mapbox isochrone service', - exception=ce) - return [] - - def calculate_isochrone(self, origin, time_ranges, - profile=DEFAULT_PROFILE): - self._validate_profile(profile) - - return self._calculate_isoline(origin=origin, - time_ranges=time_ranges, - profile=profile) - - def calculate_isodistance(self, origin, distance_range, - profile=DEFAULT_PROFILE): - self._validate_profile(profile) - - max_speed = MAX_SPEEDS[profile] - time_range = distance_range / max_speed - - return self._calculate_isoline(origin=origin, - time_ranges=[time_range], - profile=profile)[0].coordinates - - -class MapboxTrueIsochronesResponse: - - def __init__(self, coordinates, duration): - self._coordinates = coordinates - self._duration = duration - - @property - def coordinates(self): - return self._coordinates - - @property - def duration(self): - return self._duration diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/types.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/types.py index 57c6764..cc55bac 100644 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/types.py +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/types.py @@ -1,7 +1,6 @@ MAPBOX_ROUTING_APIKEY_ROUNDROBIN = 'mapbox_routing_apikey_roundrobin' MAPBOX_GEOCODER_APIKEY_ROUNDROBIN = 'mapbox_geocoder_apikey_roundrobin' MAPBOX_ISOLINES_APIKEY_ROUNDROBIN = 'mapbox_isolines_apikey_roundrobin' -MAPBOX_ISO_ISOLINES_APIKEY_ROUNDROBIN = 'mapbox_iso_isolines_apikey_roundrobin' TRANSPORT_MODE_TO_MAPBOX = { 'car': 'driving', diff --git a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py index f767b5d..dc7625d 100644 --- a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py +++ b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py @@ -224,7 +224,6 @@ class IsolinesRoutingConfig(ServiceConfig): GEOCODER_PROVIDER_KEY = 'geocoder_provider' MAPZEN_PROVIDER = 'mapzen' MAPBOX_PROVIDER = 'mapbox' - MAPBOX_ISO_PROVIDER = 'mapbox_iso' TOMTOM_PROVIDER = 'tomtom' HEREMAPS_PROVIDER = 'heremaps' DEFAULT_PROVIDER = MAPBOX_PROVIDER @@ -256,12 +255,8 @@ class IsolinesRoutingConfig(ServiceConfig): self._mapzen_matrix_service_params = db_config.mapzen_matrix_service_params self._mapzen_isochrones_service_params = db_config.mapzen_isochrones_service_params elif self._isolines_provider == self.MAPBOX_PROVIDER: - self._mapbox_matrix_api_keys = self._db_config.mapbox_matrix_api_keys - self._mapbox_matrix_service_params = db_config.mapbox_matrix_service_params - self._mapbox_isochrones_service_params = db_config.mapbox_isochrones_service_params - elif self._isolines_provider == self.MAPBOX_ISO_PROVIDER: - self._mapbox_iso_isolines_api_keys = self._db_config.mapbox_iso_isolines_api_keys - self._mapbox_iso_isolines_service_params = db_config.mapbox_iso_isolines_service_params + self._mapbox_isolinesx_api_keys = self._db_config.mapbox_isolines_api_keys + self._mapbox_isolines_service_params = db_config.mapbox_isolines_service_params elif self._isolines_provider == self.TOMTOM_PROVIDER: self._tomtom_isolinesx_api_keys = self._db_config.tomtom_isolines_api_keys self._tomtom_isolines_service_params = db_config.tomtom_isolines_service_params @@ -274,8 +269,6 @@ class IsolinesRoutingConfig(ServiceConfig): return 'mapzen_isolines' elif self._isolines_provider == self.MAPBOX_PROVIDER: return 'mapbox_isolines' - elif self._isolines_provider == self.MAPBOX_ISO_PROVIDER: - return 'mapbox_iso_isolines' elif self._isolines_provider == self.TOMTOM_PROVIDER: return 'tomtom_isolines' @@ -324,33 +317,17 @@ class IsolinesRoutingConfig(ServiceConfig): return self._isolines_provider == self.MAPZEN_PROVIDER @property - def mapbox_matrix_api_keys(self): - return self._mapbox_matrix_api_keys + def mapbox_isolines_api_keys(self): + return self._mapbox_isolines_api_keys @property - def mapbox_matrix_service_params(self): - return self._mapbox_matrix_service_params - - @property - def mapbox_isochrones_service_params(self): - return self._mapbox_isochrones_service_params + def mapbox_isolines_service_params(self): + return self._mapbox_isolines_service_params @property def mapbox_provider(self): return self._isolines_provider == self.MAPBOX_PROVIDER - @property - def mapbox_iso_isolines_api_keys(self): - return self._mapbox_iso_isolines_api_keys - - @property - def mapbox_iso_isolines_service_params(self): - return self._mapbox_iso_isolines_service_params - - @property - def mapbox_iso_provider(self): - return self._isolines_provider == self.MAPBOX_ISO_PROVIDER - @property def tomtom_isolines_api_keys(self): return self._tomtom_isolines_api_keys @@ -640,7 +617,6 @@ class ServicesDBConfig: self._get_here_config() self._get_mapzen_config() self._get_mapbox_config() - self._get_mapbox_iso_config() self._get_tomtom_config() self._get_geocodio_config() self._get_data_observatory_config() @@ -695,10 +671,9 @@ class ServicesDBConfig: raise ConfigException('Mapbox configuration missing') mapbox_conf = json.loads(mapbox_conf_json) - self._mapbox_matrix_api_keys = mapbox_conf['matrix']['api_keys'] - self._mapbox_matrix_quota = mapbox_conf['matrix']['monthly_quota'] - self._mapbox_matrix_service_params = mapbox_conf['matrix'].get('service', {}) - self._mapbox_isochrones_service_params = mapbox_conf.get('isochrones', {}).get('service', {}) + self._mapbox_isolines_api_keys = mapbox_conf['isolines']['api_keys'] + self._mapbox_isolines_quota = mapbox_conf['isolines']['monthly_quota'] + self._mapbox_isolines_service_params = mapbox_conf.get('isolines', {}).get('service', {}) self._mapbox_routing_api_keys = mapbox_conf['routing']['api_keys'] self._mapbox_routing_quota = mapbox_conf['routing']['monthly_quota'] self._mapbox_routing_service_params = mapbox_conf['routing'].get('service', {}) @@ -706,16 +681,6 @@ class ServicesDBConfig: self._mapbox_geocoder_quota = mapbox_conf['geocoder']['monthly_quota'] self._mapbox_geocoder_service_params = mapbox_conf['geocoder'].get('service', {}) - def _get_mapbox_iso_config(self): - mapbox_iso_conf_json = self._get_conf('mapbox_iso_conf') - if not mapbox_iso_conf_json: - raise ConfigException('Mapbox True Isochrones configuration missing') - - mapbox_iso_conf = json.loads(mapbox_iso_conf_json) - self._mapbox_iso_isolines_api_keys = mapbox_iso_conf['isolines']['api_keys'] - self._mapbox_iso_isolines_quota = mapbox_iso_conf['isolines']['monthly_quota'] - self._mapbox_iso_isolines_service_params = mapbox_iso_conf.get('isolines', {}).get('service', {}) - def _get_tomtom_config(self): tomtom_conf_json = self._get_conf('tomtom_conf') if not tomtom_conf_json: @@ -836,20 +801,16 @@ class ServicesDBConfig: return self._mapzen_geocoder_service_params @property - def mapbox_matrix_api_keys(self): - return self._mapbox_matrix_api_keys + def mapbox_isolines_api_keys(self): + return self._mapbox_isolines_api_keys @property - def mapbox_matrix_monthly_quota(self): - return self._mapbox_matrix_quota + def mapbox_isolines_monthly_quota(self): + return self._mapbox_isolines_quota @property - def mapbox_matrix_service_params(self): - return self._mapbox_matrix_service_params - - @property - def mapbox_isochrones_service_params(self): - return self._mapbox_isochrones_service_params + def mapbox_isolines_service_params(self): + return self._mapbox_isolines_service_params @property def mapbox_routing_api_keys(self): @@ -875,18 +836,6 @@ class ServicesDBConfig: def mapbox_geocoder_service_params(self): return self._mapbox_geocoder_service_params - @property - def mapbox_iso_isolines_api_keys(self): - return self._mapbox_iso_isolines_api_keys - - @property - def mapbox_iso_isolines_monthly_quota(self): - return self._mapbox_iso_isolines_quota - - @property - def mapbox_iso_isolines_service_params(self): - return self._mapbox_iso_isolines_service_params - @property def tomtom_isolines_api_keys(self): return self._tomtom_isolines_api_keys diff --git a/server/lib/python/cartodb_services/cartodb_services/metrics/user.py b/server/lib/python/cartodb_services/cartodb_services/metrics/user.py index d176183..70bc9a3 100644 --- a/server/lib/python/cartodb_services/cartodb_services/metrics/user.py +++ b/server/lib/python/cartodb_services/cartodb_services/metrics/user.py @@ -22,7 +22,6 @@ class UserMetricsService: SERVICE_HERE_ISOLINES = 'here_isolines' SERVICE_MAPZEN_ISOLINES = 'mapzen_isolines' SERVICE_MAPBOX_ISOLINES = 'mapbox_isolines' - SERVICE_MAPBOX_ISO_ISOLINES = 'mapbox_iso_isolines' SERVICE_TOMTOM_ISOLINES = 'tomtom_isolines' SERVICE_MAPZEN_ROUTING = 'routing_mapzen' SERVICE_MAPBOX_ROUTING = 'routing_mapbox' @@ -40,7 +39,6 @@ class UserMetricsService: if service_type in [self.SERVICE_HERE_ISOLINES, self.SERVICE_MAPZEN_ISOLINES, self.SERVICE_MAPBOX_ISOLINES, - self.SERVICE_MAPBOX_ISO_ISOLINES, self.SERVICE_TOMTOM_ISOLINES]: return self.__used_isolines_quota(service_type, date) elif service_type in [self.SERVICE_MAPZEN_ROUTING, diff --git a/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_isolines_config.py b/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_isolines_config.py index 79baa29..5a252e9 100644 --- a/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_isolines_config.py +++ b/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_isolines_config.py @@ -92,8 +92,8 @@ class MapboxIsolinesConfigBuilder(object): def get(self): mapbox_server_conf = self._server_conf.get('mapbox_conf') - mapbox_api_keys = mapbox_server_conf['matrix']['api_keys'] - mapbox_service_params = mapbox_server_conf['matrix'].get('service', {}) + mapbox_api_keys = mapbox_server_conf['isolines']['api_keys'] + mapbox_service_params = mapbox_server_conf['isolines'].get('service', {}) isolines_quota = self._get_quota() soft_isolines_limit = self._user_conf.get('soft_here_isolines_limit').lower() == 'true' diff --git a/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py b/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py deleted file mode 100644 index 7dbb445..0000000 --- a/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_true_isolines_config.py +++ /dev/null @@ -1,123 +0,0 @@ -from dateutil.parser import parse as date_parse -from cartodb_services.refactor.service.utils import round_robin -from cartodb_services.mapbox.types import MAPBOX_ISO_ISOLINES_APIKEY_ROUNDROBIN - - -class MapboxTrueIsolinesConfig(object): - """ - Configuration needed to operate the Mapbox directions service. - """ - - def __init__(self, - isolines_quota, - soft_isolines_limit, - period_end_date, - cost_per_hit, - log_path, - mapbox_api_keys, - username, - organization, - service_params, - GD): - self._isolines_quota = isolines_quota - self._soft_isolines_limit = soft_isolines_limit - self._period_end_date = period_end_date - self._cost_per_hit = cost_per_hit - self._log_path = log_path - self._mapbox_api_keys = mapbox_api_keys - self._username = username - self._organization = organization - self._service_params = service_params - self._GD = GD - - @property - def service_type(self): - return 'mapbox_isolines' - - @property - def provider(self): - return 'mapbox' - - @property - def is_high_resolution(self): - return True - - @property - def isolines_quota(self): - return self._isolines_quota - - @property - def soft_isolines_limit(self): - return self._soft_isolines_limit - - @property - def period_end_date(self): - return self._period_end_date - - @property - def cost_per_hit(self): - return self._cost_per_hit - - @property - def log_path(self): - return self._log_path - - @property - def mapbox_api_key(self): - return round_robin(self._mapbox_api_keys, self._GD, - MAPBOX_ISO_ISOLINES_APIKEY_ROUNDROBIN) - - @property - def username(self): - return self._username - - @property - def organization(self): - return self._organization - - @property - def service_params(self): - return self._service_params - - -class MapboxTrueIsolinesConfigBuilder(object): - - def __init__(self, server_conf, user_conf, org_conf, username, orgname, GD): - self._server_conf = server_conf - self._user_conf = user_conf - self._org_conf = org_conf - self._username = username - self._orgname = orgname - self._GD = GD - - def get(self): - mapbox_server_conf = self._server_conf.get('mapbox_iso_conf') - mapbox_api_keys = mapbox_server_conf['isolines']['api_keys'] - mapbox_service_params = mapbox_server_conf['isolines'].get('service', {}) - - isolines_quota = self._get_quota() - soft_isolines_limit = self._user_conf.get('soft_here_isolines_limit').lower() == 'true' - cost_per_hit = 0 - period_end_date_str = self._org_conf.get('period_end_date') or self._user_conf.get('period_end_date') - period_end_date = date_parse(period_end_date_str) - - logger_conf = self._server_conf.get('logger_conf') - log_path = logger_conf.get('isolines_log_path', None) - - return MapboxTrueIsolinesConfig(isolines_quota, - soft_isolines_limit, - period_end_date, - cost_per_hit, - log_path, - mapbox_api_keys, - self._username, - self._orgname, - mapbox_service_params, - self._GD) - - def _get_quota(self): - isolines_quota = self._org_conf.get('here_isolines_quota') or self._user_conf.get('here_isolines_quota') - if isolines_quota is '': - return 0 - - return int(isolines_quota) diff --git a/server/lib/python/cartodb_services/test/metrics/test_config.py b/server/lib/python/cartodb_services/test/metrics/test_config.py index 0fdd6f8..a933a66 100644 --- a/server/lib/python/cartodb_services/test/metrics/test_config.py +++ b/server/lib/python/cartodb_services/test/metrics/test_config.py @@ -180,7 +180,7 @@ class TestGeocoderOrgConfig(TestCase): class TestIsolinesUserConfig(TestCase): # Don't test mapbox. See CartoDB/cartodb-management/issues/5199" - ISOLINES_PROVIDERS = ['heremaps', 'mapzen', 'tomtom', 'mapbox_iso'] + ISOLINES_PROVIDERS = ['heremaps', 'mapzen', 'tomtom'] def setUp(self): self.redis_conn = MockRedis() @@ -196,8 +196,6 @@ class TestIsolinesUserConfig(TestCase): assert isolines_config.service_type is 'mapzen_isolines' elif isolines_provider is 'mapbox': assert isolines_config.service_type is 'mapbox_isolines' - elif isolines_provider is 'mapbox_iso': - assert isolines_config.service_type is 'mapbox_iso_isolines' elif isolines_provider is 'tomtom': assert isolines_config.service_type is 'tomtom_isolines' else: diff --git a/server/lib/python/cartodb_services/test/test_helper.py b/server/lib/python/cartodb_services/test/test_helper.py index fed0839..82bb84b 100644 --- a/server/lib/python/cartodb_services/test/test_helper.py +++ b/server/lib/python/cartodb_services/test/test_helper.py @@ -76,8 +76,7 @@ def increment_service_uses(redis_conn, username, orgname=None, def plpy_mock_config(): plpy_mock._define_result("CDB_Conf_GetConf\('heremaps_conf'\)", [{'conf': '{"geocoder": {"app_id": "app_id", "app_code": "code", "geocoder_cost_per_hit": 1}, "isolines": {"app_id": "app_id", "app_code": "code"}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('mapzen_conf'\)", [{'conf': '{"routing": {"api_key": "api_key_rou", "monthly_quota": 1500000}, "geocoder": {"api_key": "api_key_geo", "monthly_quota": 1500000}, "matrix": {"api_key": "api_key_mat", "monthly_quota": 1500000}}'}]) - plpy_mock._define_result("CDB_Conf_GetConf\('mapbox_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) - plpy_mock._define_result("CDB_Conf_GetConf\('mapbox_iso_conf'\)", [{'conf': '{"isolines": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) + plpy_mock._define_result("CDB_Conf_GetConf\('mapbox_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('tomtom_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('geocodio_conf'\)", [{'conf': '{"geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('logger_conf'\)", [{'conf': '{"geocoder_log_path": "/dev/null"}'}]) diff --git a/server/lib/python/cartodb_services/test/test_mapboxisoline.py b/server/lib/python/cartodb_services/test/test_mapboxisoline.py index 091ac7c..4ba38a0 100644 --- a/server/lib/python/cartodb_services/test/test_mapboxisoline.py +++ b/server/lib/python/cartodb_services/test/test_mapboxisoline.py @@ -1,20 +1,27 @@ import unittest from mock import Mock -from cartodb_services.mapbox.isolines import MapboxIsolines -from cartodb_services.mapbox.matrix_client import DEFAULT_PROFILE -from cartodb_services.mapbox.matrix_client import MapboxMatrixClient +from cartodb_services.mapbox.isolines import MapboxIsolines, DEFAULT_PROFILE from cartodb_services.tools import Coordinate + from credentials import mapbox_api_key VALID_ORIGIN = Coordinate(-73.989, 40.733) -@unittest.skip("Stop using Matrix API. CartoDB/cartodb-management/issues/5199") class MapboxIsolinesTestCase(unittest.TestCase): def setUp(self): - matrix_client = MapboxMatrixClient(token=mapbox_api_key(), logger=Mock()) - self.mapbox_isolines = MapboxIsolines(matrix_client, logger=Mock()) + self.mapbox_isolines = MapboxIsolines(apikey=mapbox_api_key(), + logger=Mock()) + + def test_invalid_time_range(self): + time_ranges = [4000] + + with self.assertRaises(ValueError): + solution = self.mapbox_isolines.calculate_isochrone( + origin=VALID_ORIGIN, + profile=DEFAULT_PROFILE, + time_ranges=time_ranges) def test_calculate_isochrone(self): time_ranges = [300, 900] diff --git a/server/lib/python/cartodb_services/test/test_mapboxmatrix.py b/server/lib/python/cartodb_services/test/test_mapboxmatrix.py deleted file mode 100644 index b1ce42e..0000000 --- a/server/lib/python/cartodb_services/test/test_mapboxmatrix.py +++ /dev/null @@ -1,58 +0,0 @@ -import unittest -from mock import Mock -from cartodb_services.mapbox import MapboxMatrixClient -from cartodb_services.mapbox.matrix_client import DEFAULT_PROFILE -from cartodb_services.tools.exceptions import ServiceException -from cartodb_services.tools import Coordinate -from credentials import mapbox_api_key - -INVALID_TOKEN = 'invalid_token' -VALID_ORIGIN = Coordinate(-73.989, 40.733) -VALID_TARGET = Coordinate(-74, 40.733) -VALID_COORDINATES = [VALID_ORIGIN] + [VALID_TARGET] -NUM_COORDINATES_MAX = 25 -INVALID_COORDINATES_EMPTY = [] -INVALID_COORDINATES_MIN = [VALID_ORIGIN] -INVALID_COORDINATES_MAX = [VALID_ORIGIN] + \ - [VALID_TARGET - for x in range(0, NUM_COORDINATES_MAX + 1)] -VALID_PROFILE = DEFAULT_PROFILE -INVALID_PROFILE = 'invalid_profile' - - -@unittest.skip("Stop using Matrix API. CartoDB/cartodb-management/issues/5199") -class MapboxMatrixTestCase(unittest.TestCase): - def setUp(self): - self.matrix_client = MapboxMatrixClient(token=mapbox_api_key(), - logger=Mock()) - - def test_invalid_profile(self): - with self.assertRaises(ValueError): - self.matrix_client.matrix(VALID_COORDINATES, - INVALID_PROFILE) - - def test_invalid_coordinates_empty(self): - with self.assertRaises(ValueError): - self.matrix_client.matrix(INVALID_COORDINATES_EMPTY, - VALID_PROFILE) - - def test_invalid_coordinates_max(self): - with self.assertRaises(ValueError): - self.matrix_client.matrix(INVALID_COORDINATES_MAX, - VALID_PROFILE) - - def test_invalid_coordinates_min(self): - with self.assertRaises(ValueError): - self.matrix_client.matrix(INVALID_COORDINATES_MIN, - VALID_PROFILE) - - def test_invalid_token(self): - invalid_matrix = MapboxMatrixClient(token=INVALID_TOKEN, logger=Mock()) - with self.assertRaises(ServiceException): - invalid_matrix.matrix(VALID_COORDINATES, - VALID_PROFILE) - - def test_valid_request(self): - distance_matrix = self.matrix_client.matrix(VALID_COORDINATES, - VALID_PROFILE) - assert distance_matrix diff --git a/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py b/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py deleted file mode 100644 index 229496f..0000000 --- a/server/lib/python/cartodb_services/test/test_mapboxtrueisoline.py +++ /dev/null @@ -1,42 +0,0 @@ -import unittest -from mock import Mock -from cartodb_services.mapbox.true_isolines import MapboxTrueIsolines, DEFAULT_PROFILE -from cartodb_services.tools import Coordinate - -from credentials import mapbox_api_key - -VALID_ORIGIN = Coordinate(-73.989, 40.733) - - -class MapboxTrueIsolinesTestCase(unittest.TestCase): - - def setUp(self): - self.mapbox_isolines = MapboxTrueIsolines(apikey=mapbox_api_key(), - logger=Mock()) - - def test_invalid_time_range(self): - time_ranges = [4000] - - with self.assertRaises(ValueError): - solution = self.mapbox_isolines.calculate_isochrone( - origin=VALID_ORIGIN, - profile=DEFAULT_PROFILE, - time_ranges=time_ranges) - - def test_calculate_isochrone(self): - time_ranges = [300, 900] - solution = self.mapbox_isolines.calculate_isochrone( - origin=VALID_ORIGIN, - profile=DEFAULT_PROFILE, - time_ranges=time_ranges) - - assert solution - - def test_calculate_isodistance(self): - distance_range = 10000 - solution = self.mapbox_isolines.calculate_isodistance( - origin=VALID_ORIGIN, - profile=DEFAULT_PROFILE, - distance_range=distance_range) - - assert solution diff --git a/server/lib/python/cartodb_services/test/test_quota_service.py b/server/lib/python/cartodb_services/test/test_quota_service.py index 9c95dc1..ce1ca21 100644 --- a/server/lib/python/cartodb_services/test/test_quota_service.py +++ b/server/lib/python/cartodb_services/test/test_quota_service.py @@ -178,23 +178,6 @@ class TestQuotaService(TestCase): qs.increment_isolines_service_use(amount=1500000) assert qs.check_user_quota() is False - def test_should_check_user_mapbox_iso_isolines_quota_correctly(self): - qs = self.__build_isolines_quota_service('test_user', - provider='mapbox_iso') - qs.increment_isolines_service_use() - assert qs.check_user_quota() is True - qs.increment_isolines_service_use(amount=1500000) - assert qs.check_user_quota() is False - - def test_should_check_org_mapbox_iso_isolines_quota_correctly(self): - qs = self.__build_isolines_quota_service('test_user', - provider='mapbox_iso', - orgname='testorg') - qs.increment_isolines_service_use() - assert qs.check_user_quota() is True - qs.increment_isolines_service_use(amount=1500000) - assert qs.check_user_quota() is False - # Quick workaround so we don't take into account numer of credits # spent for users that have defined the quota. # See https://github.com/CartoDB/bigmetadata/issues/215 From 34e715f460a1070b73fe6cae8e2da64550551e06 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Tue, 11 Feb 2020 10:01:37 +0100 Subject: [PATCH 16/20] Deleted old mapbox isolines implementation (server extension) --- ...db_dataservices_server--0.36.0--0.37.0.sql | 138 ++------------ ...db_dataservices_server--0.37.0--0.36.0.sql | 175 +++++++++++------- .../cdb_dataservices_server--0.37.0.sql | 167 +---------------- server/extension/sql/80_isolines_helper.sql | 134 +------------- server/extension/sql/85_isodistance.sql | 17 -- server/extension/sql/90_isochrone.sql | 16 -- .../test/expected/00_install_test.out | 10 +- server/extension/test/sql/00_install_test.sql | 5 +- 8 files changed, 141 insertions(+), 521 deletions(-) diff --git a/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql b/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql index 79da431..43609ac 100644 --- a/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql +++ b/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql @@ -3,7 +3,7 @@ -- HERE goes your code to upgrade/downgrade -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isodistance( +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( username TEXT, orgname TEXT, source geometry(Geometry, 4326), @@ -12,19 +12,19 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isodistance( options text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxTrueIsolines + from cartodb_services.mapbox import MapboxIsolines from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX from cartodb_services.tools import Coordinate - from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder import cartodb_services cartodb_services.init(plpy, GD) - service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) service_manager.assert_within_limits() try: - mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) if source: lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] @@ -38,7 +38,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ # -- TODO Support options properly isolines = {} for r in data_range: - isoline = mapbox_iso_isolines.calculate_isodistance(origin, r, profile) + isoline = mapbox_isolines.calculate_isodistance(origin, r, profile) isolines[r] = isoline result = [] @@ -61,14 +61,13 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ except BaseException as e: import sys service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox true isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox true isolines') + service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isolines') finally: service_manager.quota_service.increment_total_service_use() $$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isochrones( +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( username TEXT, orgname TEXT, source geometry(Geometry, 4326), @@ -77,20 +76,20 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isochrones( options text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxTrueIsolines + from cartodb_services.mapbox import MapboxIsolines from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX from cartodb_services.tools import Coordinate from cartodb_services.tools.coordinates import coordinates_to_polygon - from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder import cartodb_services cartodb_services.init(plpy, GD) - service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) service_manager.assert_within_limits() try: - mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) if source: lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] @@ -101,7 +100,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - resp = mapbox_iso_isolines.calculate_isochrone(origin, data_range, profile) + resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile) if resp: result = [] @@ -120,113 +119,8 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ except BaseException as e: import sys service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox true isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox true isochrones') + service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isochrones') finally: service_manager.quota_service.increment_total_service_use() $$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) - - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - if user_isolines_config.google_services_user: - raise Exception('This service is not available for google service users.') - - params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} - - with metrics('cdb_isodistance', user_isolines_config, logger, params): - if user_isolines_config.heremaps_provider: - here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapzen_provider: - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_provider: - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_iso_provider: - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.tomtom_provider: - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) - else: - raise Exception('Requested isolines provider is not available') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - if user_isolines_config.google_services_user: - raise Exception('This service is not available for google service users.') - - params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} - - with metrics('cdb_isochrone', user_isolines_config, logger, params): - if user_isolines_config.heremaps_provider: - here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapzen_provider: - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_provider: - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_iso_provider: - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.tomtom_provider: - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) - else: - raise Exception('Requested isolines provider is not available') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; diff --git a/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql b/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql index e418cbc..3124830 100644 --- a/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql +++ b/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql @@ -3,80 +3,127 @@ -- HERE goes your code to upgrade/downgrade -DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_iso_isodistance; - -DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_iso_isochrones; - -DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_mapbox_iso_isodistance; - -DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_mapbox_iso_isochrone; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) + import cartodb_services + cartodb_services.init(plpy, GD) - if user_isolines_config.google_services_user: - raise Exception('This service is not available for google service users.') + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() - params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + try: + client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + mapbox_isolines = MapboxIsolines(client, service_manager.logger) - with metrics('cdb_isodistance', user_isolines_config, logger, params): - if user_isolines_config.heremaps_provider: - here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapzen_provider: - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_provider: - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.tomtom_provider: - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) else: - raise Exception('Requested isolines provider is not available') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + raise Exception('source is NULL') -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapbox_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) + import cartodb_services + cartodb_services.init(plpy, GD) - if user_isolines_config.google_services_user: - raise Exception('This service is not available for google service users.') + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() - params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + try: + client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + mapbox_isolines = MapboxIsolines(client, service_manager.logger) - with metrics('cdb_isochrone', user_isolines_config, logger, params): - if user_isolines_config.heremaps_provider: - here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapzen_provider: - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_provider: - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.tomtom_provider: - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) else: - raise Exception('Requested isolines provider is not available') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; diff --git a/server/extension/cdb_dataservices_server--0.37.0.sql b/server/extension/cdb_dataservices_server--0.37.0.sql index 564e3d3..b8fb460 100644 --- a/server/extension/cdb_dataservices_server--0.37.0.sql +++ b/server/extension/cdb_dataservices_server--0.37.0.sql @@ -3395,7 +3395,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( options text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox import MapboxIsolines from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX from cartodb_services.tools import Coordinate from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder @@ -3407,8 +3407,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.assert_within_limits() try: - client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - mapbox_isolines = MapboxIsolines(client, service_manager.logger) + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) if source: lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] @@ -3432,7 +3431,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ # -- TODO encapsulate this block into a func/method locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) - sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates) + sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) multipolygon = plpy.execute(sql, 1)[0]['geom'] else: multipolygon = None @@ -3451,70 +3450,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.quota_service.increment_total_service_use() $$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isodistance( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxTrueIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - # -- TODO Support options properly - isolines = {} - for r in data_range: - isoline = mapbox_iso_isolines.calculate_isodistance(origin, r, profile) - isolines[r] = isoline - - result = [] - for r in data_range: - - if len(isolines[r]) >= 3: - # -- TODO encapsulate this block into a func/method - locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point - wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) - sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) - multipolygon = plpy.execute(sql, 1)[0]['geom'] - else: - multipolygon = None - - result.append([source, r, multipolygon]) - - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(isolines)) - return result - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox true isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox true isolines') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance( username TEXT, orgname TEXT, @@ -3649,7 +3584,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( options text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox import MapboxIsolines from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX from cartodb_services.tools import Coordinate from cartodb_services.tools.coordinates import coordinates_to_polygon @@ -3662,8 +3597,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.assert_within_limits() try: - client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - mapbox_isolines = MapboxIsolines(client, service_manager.logger) + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) if source: lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] @@ -3699,64 +3633,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.quota_service.increment_total_service_use() $$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isochrones( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxTrueIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.tools.coordinates import coordinates_to_polygon - from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - resp = mapbox_iso_isolines.calculate_isochrone(origin, data_range, profile) - - if resp: - result = [] - for isochrone in resp: - result_polygon = coordinates_to_polygon(isochrone.coordinates) - if result_polygon: - result.append([source, isochrone.duration, result_polygon]) - else: - result.append([source, isochrone.duration, None]) - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(result)) - return result - else: - service_manager.quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox true isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox true isochrones') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones( username TEXT, orgname TEXT, @@ -3842,9 +3718,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ elif user_isolines_config.mapbox_provider: mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_iso_provider: - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) elif user_isolines_config.tomtom_provider: tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) @@ -3895,20 +3768,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ return result $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; --- mapbox true isodistance -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) - - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -- tomtom isodistance CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ @@ -3950,9 +3809,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ elif user_isolines_config.mapbox_provider: mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_iso_provider: - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) elif user_isolines_config.tomtom_provider: tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) @@ -4001,19 +3857,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ return result $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; --- mapbox true isochrone -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -- tomtom isochrone CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ diff --git a/server/extension/sql/80_isolines_helper.sql b/server/extension/sql/80_isolines_helper.sql index 988855a..a259676 100644 --- a/server/extension/sql/80_isolines_helper.sql +++ b/server/extension/sql/80_isolines_helper.sql @@ -132,7 +132,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( options text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox import MapboxIsolines from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX from cartodb_services.tools import Coordinate from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder @@ -144,8 +144,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.assert_within_limits() try: - client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - mapbox_isolines = MapboxIsolines(client, service_manager.logger) + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) if source: lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] @@ -169,7 +168,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ # -- TODO encapsulate this block into a func/method locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) - sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates) + sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) multipolygon = plpy.execute(sql, 1)[0]['geom'] else: multipolygon = None @@ -188,70 +187,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.quota_service.increment_total_service_use() $$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isodistance( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxTrueIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - # -- TODO Support options properly - isolines = {} - for r in data_range: - isoline = mapbox_iso_isolines.calculate_isodistance(origin, r, profile) - isolines[r] = isoline - - result = [] - for r in data_range: - - if len(isolines[r]) >= 3: - # -- TODO encapsulate this block into a func/method - locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point - wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) - sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) - multipolygon = plpy.execute(sql, 1)[0]['geom'] - else: - multipolygon = None - - result.append([source, r, multipolygon]) - - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(isolines)) - return result - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox true isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox true isolines') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance( username TEXT, orgname TEXT, @@ -386,7 +321,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( options text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox import MapboxIsolines from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX from cartodb_services.tools import Coordinate from cartodb_services.tools.coordinates import coordinates_to_polygon @@ -399,8 +334,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.assert_within_limits() try: - client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - mapbox_isolines = MapboxIsolines(client, service_manager.logger) + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) if source: lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] @@ -436,64 +370,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ service_manager.quota_service.increment_total_service_use() $$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_iso_isochrones( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxTrueIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.tools.coordinates import coordinates_to_polygon - from cartodb_services.refactor.service.mapbox_true_isolines_config import MapboxTrueIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxTrueIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - mapbox_iso_isolines = MapboxTrueIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - resp = mapbox_iso_isolines.calculate_isochrone(origin, data_range, profile) - - if resp: - result = [] - for isochrone in resp: - result_polygon = coordinates_to_polygon(isochrone.coordinates) - if result_polygon: - result.append([source, isochrone.duration, result_polygon]) - else: - result.append([source, isochrone.duration, None]) - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(result)) - return result - else: - service_manager.quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox true isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox true isochrones') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones( username TEXT, orgname TEXT, diff --git a/server/extension/sql/85_isodistance.sql b/server/extension/sql/85_isodistance.sql index 85811ee..fbe192e 100644 --- a/server/extension/sql/85_isodistance.sql +++ b/server/extension/sql/85_isodistance.sql @@ -26,9 +26,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ elif user_isolines_config.mapbox_provider: mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_iso_provider: - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) elif user_isolines_config.tomtom_provider: tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) @@ -79,20 +76,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ return result $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; --- mapbox true isodistance -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) - - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -- tomtom isodistance CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ diff --git a/server/extension/sql/90_isochrone.sql b/server/extension/sql/90_isochrone.sql index 035ab0f..731a27e 100644 --- a/server/extension/sql/90_isochrone.sql +++ b/server/extension/sql/90_isochrone.sql @@ -26,9 +26,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ elif user_isolines_config.mapbox_provider: mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_iso_provider: - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_iso_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) elif user_isolines_config.tomtom_provider: tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) @@ -77,19 +74,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$ return result $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; --- mapbox true isochrone -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_iso_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapbox_iso_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_iso_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapbox_iso_plan, [username, orgname, source, mode, range, options]) - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -- tomtom isochrone CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) RETURNS SETOF cdb_dataservices_server.isoline AS $$ diff --git a/server/extension/test/expected/00_install_test.out b/server/extension/test/expected/00_install_test.out index 53431a7..43c6941 100644 --- a/server/extension/test/expected/00_install_test.out +++ b/server/extension/test/expected/00_install_test.out @@ -33,19 +33,13 @@ SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"routing": {"api_key": "routing (1 row) -SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); +SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["isolines_dummy_api_key"], "monthly_quota": 1500000}}'); cdb_conf_setconf ------------------ (1 row) -SELECT cartodb.cdb_conf_setconf('mapbox_iso_conf', '{"isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); - cdb_conf_setconf ------------------- - -(1 row) - -SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); +SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["isolines_dummy_api_key"], "monthly_quota": 1500000}}'); cdb_conf_setconf ------------------ diff --git a/server/extension/test/sql/00_install_test.sql b/server/extension/test/sql/00_install_test.sql index c291021..2a4ef6b 100644 --- a/server/extension/test/sql/00_install_test.sql +++ b/server/extension/test/sql/00_install_test.sql @@ -15,9 +15,8 @@ SELECT cartodb.cdb_conf_setconf('redis_metrics_config', '{"redis_host": "localho SELECT cartodb.cdb_conf_setconf('redis_metadata_config', '{"redis_host": "localhost", "redis_port": 6379, "timeout": 0.1, "redis_db": 5}'); SELECT cartodb.cdb_conf_setconf('heremaps_conf', '{"geocoder": {"app_id": "dummy_id", "app_code": "dummy_code", "geocoder_cost_per_hit": 1}, "isolines": {"app_id": "dummy_id", "app_code": "dummy_code"}}'); SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"routing": {"api_key": "routing_dummy_api_key", "monthly_quota": 1500000}, "geocoder": {"api_key": "geocoder_dummy_api_key", "monthly_quota": 1500000}, "matrix": {"api_key": "matrix_dummy_api_key", "monthly_quota": 1500000}}'); -SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); -SELECT cartodb.cdb_conf_setconf('mapbox_iso_conf', '{"isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); -SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); +SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["isolines_dummy_api_key"], "monthly_quota": 1500000}}'); +SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["isolines_dummy_api_key"], "monthly_quota": 1500000}}'); SELECT cartodb.cdb_conf_setconf('geocodio_conf', '{"geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}}'); SELECT cartodb.cdb_conf_setconf('logger_conf', '{"geocoder_log_path": "/dev/null"}'); SELECT cartodb.cdb_conf_setconf('data_observatory_conf', '{"connection": {"whitelist": ["ethervoid"], "production": "host=localhost port=5432 dbname=contrib_regression user=geocoder_api", "staging": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api"}, "monthly_quota": 100000}'); From ab71acd4619b411c1e9b80fd6e07dd31f10c1c2e Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Tue, 11 Feb 2020 14:08:19 +0100 Subject: [PATCH 17/20] Removed generated files to ease review --- ...db_dataservices_server--0.35.1--0.36.0.sql | 0 ...db_dataservices_server--0.36.0--0.35.1.sql | 0 ...db_dataservices_server--0.36.0--0.37.0.sql | 126 - .../cdb_dataservices_server--0.36.0.sql | 0 ...db_dataservices_server--0.37.0--0.36.0.sql | 129 - .../cdb_dataservices_server--0.37.0.sql | 3886 ----------------- 6 files changed, 4141 deletions(-) rename server/extension/{old_versions => }/cdb_dataservices_server--0.35.1--0.36.0.sql (100%) rename server/extension/{old_versions => }/cdb_dataservices_server--0.36.0--0.35.1.sql (100%) delete mode 100644 server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql rename server/extension/{old_versions => }/cdb_dataservices_server--0.36.0.sql (100%) delete mode 100644 server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql delete mode 100644 server/extension/cdb_dataservices_server--0.37.0.sql diff --git a/server/extension/old_versions/cdb_dataservices_server--0.35.1--0.36.0.sql b/server/extension/cdb_dataservices_server--0.35.1--0.36.0.sql similarity index 100% rename from server/extension/old_versions/cdb_dataservices_server--0.35.1--0.36.0.sql rename to server/extension/cdb_dataservices_server--0.35.1--0.36.0.sql diff --git a/server/extension/old_versions/cdb_dataservices_server--0.36.0--0.35.1.sql b/server/extension/cdb_dataservices_server--0.36.0--0.35.1.sql similarity index 100% rename from server/extension/old_versions/cdb_dataservices_server--0.36.0--0.35.1.sql rename to server/extension/cdb_dataservices_server--0.36.0--0.35.1.sql diff --git a/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql b/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql deleted file mode 100644 index 43609ac..0000000 --- a/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql +++ /dev/null @@ -1,126 +0,0 @@ --- Complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.37.0'" to load this file. \quit - --- HERE goes your code to upgrade/downgrade - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - # -- TODO Support options properly - isolines = {} - for r in data_range: - isoline = mapbox_isolines.calculate_isodistance(origin, r, profile) - isolines[r] = isoline - - result = [] - for r in data_range: - - if len(isolines[r]) >= 3: - # -- TODO encapsulate this block into a func/method - locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point - wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) - sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) - multipolygon = plpy.execute(sql, 1)[0]['geom'] - else: - multipolygon = None - - result.append([source, r, multipolygon]) - - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(isolines)) - return result - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox isolines') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.tools.coordinates import coordinates_to_polygon - from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile) - - if resp: - result = [] - for isochrone in resp: - result_polygon = coordinates_to_polygon(isochrone.coordinates) - if result_polygon: - result.append([source, isochrone.duration, result_polygon]) - else: - result.append([source, isochrone.duration, None]) - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(result)) - return result - else: - service_manager.quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox isochrones') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; diff --git a/server/extension/old_versions/cdb_dataservices_server--0.36.0.sql b/server/extension/cdb_dataservices_server--0.36.0.sql similarity index 100% rename from server/extension/old_versions/cdb_dataservices_server--0.36.0.sql rename to server/extension/cdb_dataservices_server--0.36.0.sql diff --git a/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql b/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql deleted file mode 100644 index 3124830..0000000 --- a/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql +++ /dev/null @@ -1,129 +0,0 @@ --- Complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.36.0'" to load this file. \quit - --- HERE goes your code to upgrade/downgrade - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - mapbox_isolines = MapboxIsolines(client, service_manager.logger) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - # -- TODO Support options properly - isolines = {} - for r in data_range: - isoline = mapbox_isolines.calculate_isodistance(origin, r, profile) - isolines[r] = isoline - - result = [] - for r in data_range: - - if len(isolines[r]) >= 3: - # -- TODO encapsulate this block into a func/method - locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point - wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) - sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates) - multipolygon = plpy.execute(sql, 1)[0]['geom'] - else: - multipolygon = None - - result.append([source, r, multipolygon]) - - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(isolines)) - return result - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox isolines') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.tools.coordinates import coordinates_to_polygon - from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - mapbox_isolines = MapboxIsolines(client, service_manager.logger) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile) - - if resp: - result = [] - for isochrone in resp: - result_polygon = coordinates_to_polygon(isochrone.coordinates) - if result_polygon: - result.append([source, isochrone.duration, result_polygon]) - else: - result.append([source, isochrone.duration, None]) - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(result)) - return result - else: - service_manager.quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox isochrones') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; diff --git a/server/extension/cdb_dataservices_server--0.37.0.sql b/server/extension/cdb_dataservices_server--0.37.0.sql deleted file mode 100644 index b8fb460..0000000 --- a/server/extension/cdb_dataservices_server--0.37.0.sql +++ /dev/null @@ -1,3886 +0,0 @@ ---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_server" to load this file. \quit -CREATE TYPE cdb_dataservices_server.simple_route AS ( - shape geometry(LineString,4326), - length real, - duration integer -); - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_route_with_waypoints( - username TEXT, - orgname TEXT, - waypoints geometry(Point, 4326)[], - mode TEXT, - options text[] DEFAULT ARRAY[]::text[], - units text DEFAULT 'kilometers') -RETURNS cdb_dataservices_server.simple_route AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxRouting - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.tools.polyline import polyline_to_linestring - from cartodb_services.tools.normalize import options_to_dict - from cartodb_services.refactor.service.mapbox_routing_config import MapboxRoutingConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('routing', MapboxRoutingConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - client = MapboxRouting(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - if not waypoints or len(waypoints) < 2: - service_manager.logger.info("Empty origin or destination") - service_manager.quota_service.increment_empty_service_use() - return [None, None, None] - - if len(waypoints) > 25: - service_manager.logger.info("Too many waypoints (max 25)") - service_manager.quota_service.increment_empty_service_use() - return [None, None, None] - - waypoint_coords = [] - for waypoint in waypoints: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon'] - waypoint_coords.append(Coordinate(lon,lat)) - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - options_dict = options_to_dict(options) - if 'mode_type' in options_dict: - plpy.warning('Mapbox provider doesnt support route type parameter') - - resp = client.directions(waypoint_coords, profile) - if resp and resp.shape: - shape_linestring = polyline_to_linestring(resp.shape) - if shape_linestring: - service_manager.quota_service.increment_success_service_use() - return [shape_linestring, resp.length, int(round(resp.duration))] - else: - service_manager.quota_service.increment_empty_service_use() - return [None, None, None] - else: - service_manager.quota_service.increment_empty_service_use() - return [None, None, None] - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to calculate Mapbox routing', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to calculate Mapbox routing') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoints( - username TEXT, - orgname TEXT, - waypoints geometry(Point, 4326)[], - mode TEXT, - options text[] DEFAULT ARRAY[]::text[], - units text DEFAULT 'kilometers') -RETURNS cdb_dataservices_server.simple_route AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.tomtom import TomTomRouting - from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM, DEFAULT_ROUTE_TYPE, MODE_TYPE_TO_TOMTOM - from cartodb_services.tools import Coordinate - from cartodb_services.tools.polyline import polyline_to_linestring - from cartodb_services.tools.normalize import options_to_dict - from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('routing', TomTomRoutingConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - client = TomTomRouting(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) - - if not waypoints or len(waypoints) < 2: - service_manager.logger.info("Empty origin or destination") - service_manager.quota_service.increment_empty_service_use() - return [None, None, None] - - if len(waypoints) > 25: - service_manager.logger.info("Too many waypoints (max 25)") - service_manager.quota_service.increment_empty_service_use() - return [None, None, None] - - waypoint_coords = [] - for waypoint in waypoints: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon'] - waypoint_coords.append(Coordinate(lon,lat)) - - profile = TRANSPORT_MODE_TO_TOMTOM.get(mode) - route_type = DEFAULT_ROUTE_TYPE - options_dict = options_to_dict(options) - if 'mode_type' in options_dict: - route_type = MODE_TYPE_TO_TOMTOM.get(options_dict['mode_type']) - - resp = client.directions(waypoint_coords, profile=profile, route_type=route_type) - if resp and resp.shape: - shape_linestring = polyline_to_linestring(resp.shape) - if shape_linestring: - service_manager.quota_service.increment_success_service_use() - return [shape_linestring, resp.length, int(round(resp.duration))] - else: - service_manager.quota_service.increment_empty_service_use() - return [None, None, None] - else: - service_manager.quota_service.increment_empty_service_use() - return [None, None, None] - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to calculate TomTom routing', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to calculate TomTom routing') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_route_with_waypoints( - username TEXT, - orgname TEXT, - waypoints geometry(Point, 4326)[], - mode TEXT, - options text[] DEFAULT ARRAY[]::text[], - units text DEFAULT 'kilometers') -RETURNS cdb_dataservices_server.simple_route AS $$ - import json - from cartodb_services.mapzen import MapzenRouting, MapzenRoutingResponse - from cartodb_services.mapzen.types import polyline_to_linestring - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Coordinate - from cartodb_services.tools import Logger,LoggerConfig - - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - user_routing_config = GD["user_routing_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - quota_service = QuotaService(user_routing_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - try: - client = MapzenRouting(user_routing_config.mapzen_api_key, logger, user_routing_config.mapzen_service_params) - - if not waypoints or len(waypoints) < 2: - logger.info("Empty origin or destination") - quota_service.increment_empty_service_use() - return [None, None, None] - - waypoint_coords = [] - for waypoint in waypoints: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon'] - waypoint_coords.append(Coordinate(lon,lat)) - - resp = client.calculate_route_point_to_point(waypoint_coords, mode, options, units) - if resp and resp.shape: - shape_linestring = polyline_to_linestring(resp.shape) - if shape_linestring: - quota_service.increment_success_service_use() - return [shape_linestring, resp.length, resp.duration] - else: - quota_service.increment_empty_service_use() - return [None, None, None] - else: - quota_service.increment_empty_service_use() - return [None, None, None] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to calculate mapzen routing', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to calculate mapzen routing') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point( - username TEXT, - orgname TEXT, - origin geometry(Point, 4326), - destination geometry(Point, 4326), - mode TEXT, - options text[] DEFAULT ARRAY[]::text[], - units text DEFAULT 'kilometers') -RETURNS cdb_dataservices_server.simple_route AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_routing_config = GD["user_routing_config_{0}".format(username)] - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - params = {'username': username, 'orgname': orgname, 'origin': origin, 'destination': destination, 'mode': mode, 'options': options, 'units': units} - - with metrics('cdb_route_with_point', user_routing_config, logger, params): - waypoints = [origin, destination] - - if user_routing_config.mapzen_provider: - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) - result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units]) - return [result[0]['shape'],result[0]['length'], result[0]['duration']] - elif user_routing_config.mapbox_provider: - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) - result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units]) - return [result[0]['shape'],result[0]['length'], result[0]['duration']] - elif user_routing_config.tomtom_provider: - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) - result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units]) - return [result[0]['shape'],result[0]['length'], result[0]['duration']] - else: - raise Exception('Requested routing method is not available') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints( - username TEXT, - orgname TEXT, - waypoints geometry(Point, 4326)[], - mode TEXT, - options text[] DEFAULT ARRAY[]::text[], - units text DEFAULT 'kilometers') -RETURNS cdb_dataservices_server.simple_route AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_routing_config = GD["user_routing_config_{0}".format(username)] - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - params = {'username': username, 'orgname': orgname, 'waypoints': waypoints, 'mode': mode, 'options': options, 'units': units} - - with metrics('cdb_route_with_waypoints', user_routing_config, logger, params): - if user_routing_config.mapzen_provider: - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) - result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units]) - return [result[0]['shape'],result[0]['length'], result[0]['duration']] - elif user_routing_config.mapbox_provider: - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) - result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units]) - return [result[0]['shape'],result[0]['length'], result[0]['duration']] - elif user_routing_config.tomtom_provider: - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) - result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units]) - return [result[0]['shape'],result[0]['length'], result[0]['duration']] - else: - raise Exception('Requested routing method is not available') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; --- 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, RedisDBConfig - metadata_config = RedisDBConfig('redis_metadata_config', plpy) - metrics_config = RedisDBConfig('redis_metrics_config', plpy) - redis_metadata_connection = RedisConnection(metadata_config).redis_connection() - redis_metrics_connection = RedisConnection(metrics_config).redis_connection() - GD[cache_key] = { - 'redis_metadata_connection': redis_metadata_connection, - 'redis_metrics_connection': redis_metrics_connection, - } - return True -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; --- --- Observatory connection config --- --- The purpose of this function is provide to the PL/Proxy functions --- the connection string needed to connect with the current production database - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._obs_server_conn_str( - username TEXT, - orgname TEXT) -RETURNS text 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_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - return user_obs_config.connection_str -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetDemographicSnapshotJSON( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - time_span TEXT DEFAULT NULL, - geometry_level TEXT DEFAULT NULL) -RETURNS json AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetDemographicSnapshot(geom, time_span, geometry_level); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_get_demographic_snapshot( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - time_span TEXT DEFAULT NULL, - geometry_level TEXT DEFAULT NULL) -RETURNS json AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - import json - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getdemographicsnapshot', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshotJSON($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level]) - if result: - quota_service.increment_success_service_use() - return result[0]['snapshot'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to obs_get_demographic_snapshot') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetDemographicSnapshot( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - time_span TEXT DEFAULT NULL, - geometry_level TEXT DEFAULT NULL) -RETURNS SETOF json AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetDemographicSnapshot(geom, time_span, geometry_level); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetDemographicSnapshot( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - time_span TEXT DEFAULT NULL, - geometry_level TEXT DEFAULT NULL) -RETURNS SETOF JSON AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getdemographicsnapshot', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshot($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level]) - if result: - resp = [] - for element in result: - value = element['snapshot'] - resp.append(value) - quota_service.increment_success_service_use() - return resp - else: - quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to obs_get_demographic_snapshot') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetSegmentSnapshotJSON( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - geometry_level TEXT DEFAULT NULL) -RETURNS json AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetSegmentSnapshot(geom, geometry_level); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_get_segment_snapshot( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - geometry_level TEXT DEFAULT NULL) -RETURNS json AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - import json - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getsegmentsnapshot', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetSegmentSnapshotJSON($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level]) - if result: - quota_service.increment_success_service_use() - return result[0]['snapshot'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to obs_get_segment_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to obs_get_segment_snapshot') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetSegmentSnapshot( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - geometry_level TEXT DEFAULT NULL) -RETURNS SETOF json AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetSegmentSnapshot(geom, geometry_level); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetSegmentSnapshot( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - geometry_level TEXT DEFAULT NULL) -RETURNS SETOF JSON AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getsegmentsnapshot', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetSegmentSnapshot($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level]) - if result: - resp = [] - for element in result: - value = element['snapshot'] - resp.append(value) - quota_service.increment_success_service_use() - return resp - else: - quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetSegmentSnapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetSegmentSnapshot') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeasure( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - measure_id TEXT, - normalize TEXT DEFAULT NULL, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS NUMERIC AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetMeasure(geom, measure_id, normalize, boundary_id, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeasure( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - measure_id TEXT, - normalize TEXT DEFAULT NULL, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS NUMERIC AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getmeasure', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasure($1, $2, $3, $4, $5, $6, $7) as measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, measure_id, normalize, boundary_id, time_span]) - if result: - quota_service.increment_success_service_use() - return result[0]['measure'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetMeasure', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetMeasure') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetCategory( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - category_id TEXT, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS TEXT AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetCategory(geom, category_id, boundary_id, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetCategory( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - category_id TEXT, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS TEXT AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getcategory', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetCategory($1, $2, $3, $4, $5, $6) as category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, category_id, boundary_id, time_span]) - if result: - quota_service.increment_success_service_use() - return result[0]['category'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetCategory', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetCategory') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetUSCensusMeasure( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - name TEXT, - normalize TEXT DEFAULT NULL, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS NUMERIC AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetUSCensusMeasure(geom, name, normalize, boundary_id, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetUSCensusMeasure( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - name TEXT, - normalize TEXT DEFAULT NULL, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS NUMERIC AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getuscensusmeasure', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusMeasure($1, $2, $3, $4, $5, $6, $7) as census_measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, name, normalize, boundary_id, time_span]) - if result: - quota_service.increment_success_service_use() - return result[0]['census_measure'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetUSCensusMeasure', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetUSCensusMeasure') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetUSCensusCategory( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - name TEXT, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS TEXT AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetUSCensusCategory(geom, name, boundary_id, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetUSCensusCategory( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - name TEXT, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS TEXT AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getuscensuscategory', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusCategory($1, $2, $3, $4, $5, $6) as census_category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, name, boundary_id, time_span]) - if result: - quota_service.increment_success_service_use() - return result[0]['census_category'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetUSCensusCategory', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetUSCensusCategory') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPopulation( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - normalize TEXT DEFAULT NULL, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS NUMERIC AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetPopulation(geom, normalize, boundary_id, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPopulation( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - normalize TEXT DEFAULT NULL, - boundary_id TEXT DEFAULT NULL, - time_span TEXT DEFAULT NULL) -RETURNS NUMERIC AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getpopulation', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetPopulation($1, $2, $3, $4, $5, $6) as population;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, normalize, boundary_id, time_span]) - if result: - quota_service.increment_success_service_use() - return result[0]['population'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetPopulation', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetPopulation') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeasureById( - username TEXT, - orgname TEXT, - geom_ref TEXT, - measure_id TEXT, - boundary_id TEXT, - time_span TEXT DEFAULT NULL) -RETURNS NUMERIC AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetMeasureById(geom_ref, measure_id, boundary_id, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeasureById( - username TEXT, - orgname TEXT, - geom_ref TEXT, - measure_id TEXT, - boundary_id TEXT, - time_span TEXT DEFAULT NULL) -RETURNS NUMERIC AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getmeasurebyid', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasureById($1, $2, $3, $4, $5, $6) as measure;", ["text", "text", "text", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom_ref, measure_id, boundary_id, time_span]) - if result: - quota_service.increment_success_service_use() - return result[0]['measure'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetMeasureById') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData( - username TEXT, - orgname TEXT, - geomvals geomval[], - params JSON, - merge BOOLEAN DEFAULT True) -RETURNS TABLE ( - id INT, - data JSON -) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetData(geomvals, params, merge); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData( - username TEXT, - orgname TEXT, - geomvals geomval[], - params JSON, - merge BOOLEAN DEFAULT True) -RETURNS TABLE ( - id INT, - data JSON -) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getdata', user_obs_config, logger, params): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4, $5);", ["text", "text", "geomval[]", "json", "boolean"]) - result = plpy.execute(obs_plan, [username, orgname, geomvals, params, merge]) - empty_results = len(geomvals) - len(result) - if empty_results > 0: - quota_service.increment_empty_service_use(empty_results) - if result: - quota_service.increment_success_service_use(len(result)) - return result - else: - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use(len(geomvals)) - logger.error('Error trying to OBS_GetData', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetData') - finally: - quota_service.increment_total_service_use(len(geomvals)) -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData( - username TEXT, - orgname TEXT, - geomrefs TEXT[], - params JSON) -RETURNS TABLE ( - id TEXT, - data JSON -) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetData(geomrefs, params); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData( - username TEXT, - orgname TEXT, - geomrefs TEXT[], - params JSON) -RETURNS TABLE ( - id TEXT, - data JSON -) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getdata', user_obs_config, logger, params): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4);", ["text", "text", "text[]", "json"]) - result = plpy.execute(obs_plan, [username, orgname, geomrefs, params]) - empty_results = len(geomrefs) - len(result) - if empty_results > 0: - quota_service.increment_empty_service_use(empty_results) - if result: - quota_service.increment_success_service_use(len(result)) - return result - else: - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use(len(geomrefs)) - exc_info = sys.exc_info() - logger.error('%s, %s, %s' % (exc_info[0], exc_info[1], exc_info[2])) - logger.error('Error trying to OBS_GetData', exc_info, data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetData') - finally: - quota_service.increment_total_service_use(len(geomrefs)) -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeta( - username TEXT, - orgname TEXT, - geom Geometry(Geometry, 4326), - params JSON, - max_timespan_rank INTEGER DEFAULT NULL, - max_score_rank INTEGER DEFAULT NULL, - target_geoms INTEGER DEFAULT NULL) -RETURNS JSON AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetMeta(geom, params, max_timespan_rank, max_score_rank, target_geoms); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeta( - username TEXT, - orgname TEXT, - geom Geometry(Geometry, 4326), - params JSON, - max_timespan_rank INTEGER DEFAULT NULL, - max_score_rank INTEGER DEFAULT NULL, - target_geoms INTEGER DEFAULT NULL) -RETURNS JSON AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - with metrics('obs_getmeta', user_obs_config, logger, params): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeta($1, $2, $3, $4, $5, $6, $7) as meta;", ["text", "text", "Geometry (Geometry, 4326)", "json", "integer", "integer", "integer"]) - result = plpy.execute(obs_plan, [username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms]) - if result: - return result[0]['meta'] - else: - return None - except BaseException as e: - import sys - logger.error('Error trying to OBS_GetMeta', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetMeta') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_MetadataValidation( - username TEXT, - orgname TEXT, - geometry_extent Geometry(Geometry, 4326), - geometry_type text, - params JSON, - target_geoms INTEGER DEFAULT NULL) -RETURNS TABLE(valid boolean, errors text[]) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_MetadataValidation(geometry_extent, geometry_type, params, target_geoms); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_MetadataValidation( - username TEXT, - orgname TEXT, - geometry_extent Geometry(Geometry, 4326), - geometry_type text, - params JSON, - target_geoms INTEGER DEFAULT NULL) -RETURNS TABLE(valid boolean, errors text[]) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - with metrics('obs_metadatavalidation', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_MetadataValidation($1, $2, $3, $4, $5, $6);", ["text", "text", "Geometry (Geometry, 4326)", "text", "json", "integer"]) - result = plpy.execute(obs_plan, [username, orgname, geometry_extent, geometry_type, params, target_geoms]) - if result: - return result - else: - return [] - except BaseException as e: - import sys - logger.error('Error trying to OBS_MetadataValidation', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_MetadataValidation') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_Search( - username TEXT, - orgname TEXT, - search_term TEXT, - relevant_boundary TEXT DEFAULT NULL) -RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_Search(search_term, relevant_boundary); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_Search( - username TEXT, - orgname TEXT, - search_term TEXT, - relevant_boundary TEXT DEFAULT NULL) -RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_search', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_Search($1, $2, $3, $4);", ["text", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, search_term, relevant_boundary]) - if result: - resp = [] - for element in result: - id = element['id'] - description = element['description'] - name = element['name'] - aggregate = element['aggregate'] - source = element['source'] - resp.append([id, description, name, aggregate, source]) - quota_service.increment_success_service_use() - return resp - else: - quota_service.increment_empty_service_use() - return [None, None, None, None, None] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_Search', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_Search') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetAvailableBoundaries( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - time_span TEXT DEFAULT NULL) -RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetAvailableBoundaries(geom, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableBoundaries( - username TEXT, - orgname TEXT, - geom geometry(Geometry, 4326), - time_span TEXT DEFAULT NULL) -RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getavailableboundaries', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetAvailableBoundaries($1, $2, $3, $4) as available_boundaries;", ["text", "text", "geometry(Geometry, 4326)", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, time_span]) - if result: - resp = [] - for element in result: - id = element['boundary_id'] - description = element['description'] - tspan = element['time_span'] - tablename = element['tablename'] - resp.append([id, description, tspan, tablename]) - quota_service.increment_success_service_use() - return resp - else: - quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetMeasureById') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundary( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - boundary_id TEXT, - time_span TEXT DEFAULT NULL) -RETURNS geometry(Geometry, 4326) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetBoundary(geom, boundary_id, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundary( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - boundary_id TEXT, - time_span TEXT DEFAULT NULL) -RETURNS geometry(Geometry, 4326) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getboundary', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundary($1, $2, $3, $4) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span]) - if result: - quota_service.increment_success_service_use() - return result[0]['boundary'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetBoundary', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetBoundary') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundaryId( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - boundary_id TEXT, - time_span TEXT DEFAULT NULL) -RETURNS TEXT AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetBoundaryId(geom, boundary_id, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundaryId( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - boundary_id TEXT, - time_span TEXT DEFAULT NULL) -RETURNS TEXT AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getboundaryid', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryId($1, $2, $3, $4, $5) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span]) - if result: - quota_service.increment_success_service_use() - return result[0]['boundary'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetBoundaryId', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetBoundaryId') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundaryById( - username TEXT, - orgname TEXT, - geometry_id TEXT, - boundary_id TEXT, - time_span TEXT DEFAULT NULL) -RETURNS geometry(Geometry, 4326) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.OBS_GetBoundaryById(geometry_id, boundary_id, time_span); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundaryById( - username TEXT, - orgname TEXT, - geometry_id TEXT, - boundary_id TEXT, - time_span TEXT DEFAULT NULL) -RETURNS geometry(Geometry, 4326) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getboundarybyid', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryById($1, $2, $3, $4, $5) as boundary;", ["text", "text", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geometry_id, boundary_id, time_span]) - if result: - quota_service.increment_success_service_use() - return result[0]['boundary'] - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetBoundaryById', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetBoundaryById') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundariesByGeometry( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - boundary_id TEXT, - time_span TEXT DEFAULT NULL, - overlap_type text DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetBoundariesByGeometry(geom, boundary_id, time_span, overlap_type); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundariesByGeometry( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - boundary_id TEXT, - time_span TEXT DEFAULT NULL, - overlap_type TEXT DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getboundariesbygeometry', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type]) - if result: - resp = [] - for element in result: - the_geom = element['the_geom'] - geom_refs = element['geom_refs'] - resp.append([the_geom, geom_refs]) - quota_service.increment_success_service_use() - return resp - else: - quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetBoundariesByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetBoundariesByGeometry') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundariesByPointAndRadius( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - radius NUMERIC, - boundary_id TEXT, - time_span TEXT DEFAULT NULL, - overlap_type TEXT DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetBoundariesByPointAndRadius(geom, radius, boundary_id, time_span, overlap_type); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundariesByPointAndRadius( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - radius NUMERIC, - boundary_id TEXT, - time_span TEXT DEFAULT NULL, - overlap_type TEXT DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getboundariesbypointandradius', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type]) - if result: - resp = [] - for element in result: - the_geom = element['the_geom'] - geom_refs = element['geom_refs'] - resp.append([the_geom, geom_refs]) - quota_service.increment_success_service_use() - return resp - else: - quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetBoundariesByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetBoundariesByPointAndRadius') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPointsByGeometry( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - boundary_id TEXT, - time_span TEXT DEFAULT NULL, - overlap_type TEXT DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetPointsByGeometry(geom, boundary_id, time_span, overlap_type); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPointsByGeometry( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - boundary_id TEXT, - time_span TEXT DEFAULT NULL, - overlap_type TEXT DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getpointsbygeometry', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type]) - if result: - resp = [] - for element in result: - the_geom = element['the_geom'] - geom_refs = element['geom_refs'] - resp.append([the_geom, geom_refs]) - quota_service.increment_success_service_use() - return resp - else: - quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetPointsByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetPointsByGeometry') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPointsByPointAndRadius( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - radius NUMERIC, - boundary_id TEXT, - time_span TEXT DEFAULT NULL, - overlap_type TEXT DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetPointsByPointAndRadius(geom, radius, boundary_id, time_span, overlap_type); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPointsByPointAndRadius( - username TEXT, - orgname TEXT, - geom geometry(Point, 4326), - radius NUMERIC, - boundary_id TEXT, - time_span TEXT DEFAULT NULL, - overlap_type TEXT DEFAULT NULL) -RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_obs_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - with metrics('obs_getpointsbypointandradius', user_obs_config, logger): - try: - obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"]) - result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type]) - if result: - resp = [] - for element in result: - the_geom = element['the_geom'] - geom_refs = element['geom_refs'] - resp.append([the_geom, geom_refs]) - quota_service.increment_success_service_use() - return resp - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to OBS_GetPointsByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to OBS_GetPointsByPointAndRadius') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; -CREATE TYPE cdb_dataservices_server.ds_fdw_metadata as (schemaname text, tabname text, servername text); - -CREATE TYPE cdb_dataservices_server.ds_return_metadata as (colnames text[], coltypes text[]); - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_ConnectUserTable(username text, orgname text, user_db_role text, input_schema text, dbname text, table_name text) -RETURNS cdb_dataservices_server.ds_fdw_metadata AS $$ - host_addr = plpy.execute("SELECT split_part(inet_client_addr()::text, '/', 1) as user_host")[0]['user_host'] - return plpy.execute("SELECT * FROM cdb_dataservices_server.__DST_ConnectUserTable({username}::text, {orgname}::text, {user_db_role}::text, {schema}::text, {dbname}::text, {host_addr}::text, {table_name}::text)" - .format(username=plpy.quote_nullable(username), orgname=plpy.quote_nullable(orgname), user_db_role=plpy.quote_literal(user_db_role), schema=plpy.quote_literal(input_schema), dbname=plpy.quote_literal(dbname), table_name=plpy.quote_literal(table_name), host_addr=plpy.quote_literal(host_addr)) - )[0] -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.__DST_ConnectUserTable(username text, orgname text, user_db_role text, input_schema text, dbname text, host_addr text, table_name text) -RETURNS cdb_dataservices_server.ds_fdw_metadata AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - TARGET cdb_observatory._OBS_ConnectUserTable; -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_GetReturnMetadata(username text, orgname text, function_name text, params json) -RETURNS cdb_dataservices_server.ds_return_metadata AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - TARGET cdb_observatory._OBS_GetReturnMetadata; -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_FetchJoinFdwTableData(username text, orgname text, table_schema text, table_name text, function_name text, params json) -RETURNS SETOF record AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - TARGET cdb_observatory._OBS_FetchJoinFdwTableData; -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_DisconnectUserTable(username text, orgname text, table_schema text, table_name text, servername text) -RETURNS boolean AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - TARGET cdb_observatory._OBS_DisconnectUserTable; -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_dumpversion(username text, orgname text) -RETURNS text AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT cdb_observatory.obs_dumpversion(); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - --- We could create a super type for the common data like id, name and so on but we need to parse inside the functions because the -- the return data tha comes from OBS is a TABLE() with them -CREATE TYPE cdb_dataservices_server.obs_meta_numerator AS (numer_id text, numer_name text, numer_description text, numer_weight text, numer_license text, numer_source text, numer_type text, numer_aggregate text, numer_extra jsonb, numer_tags jsonb, valid_denom boolean, valid_geom boolean, valid_timespan boolean); - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableNumerators( - username TEXT, - orgname TEXT, - bounds geometry(Geometry, 4326) DEFAULT NULL, - filter_tags TEXT[] DEFAULT NULL, - denom_id TEXT DEFAULT NULL, - geom_id TEXT DEFAULT NULL, - timespan TEXT DEFAULT NULL) -RETURNS SETOF cdb_dataservices_server.obs_meta_numerator AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetAvailableNumerators(bounds, filter_tags, denom_id, geom_id, timespan); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetNumerators( - username TEXT, - orgname TEXT, - bounds geometry(Geometry, 4326) DEFAULT NULL, - section_tags TEXT[] DEFAULT ARRAY[]::TEXT[], - subsection_tags TEXT[] DEFAULT ARRAY[]::TEXT[], - other_tags TEXT[] DEFAULT ARRAY[]::TEXT[], - ids TEXT[] DEFAULT ARRAY[]::TEXT[], - name TEXT DEFAULT NULL, - denom_id TEXT DEFAULT '', - geom_id TEXT DEFAULT '', - timespan TEXT DEFAULT '') -RETURNS SETOF cdb_dataservices_server.obs_meta_numerator AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory._OBS_GetNumerators(bounds, section_tags, subsection_tags, other_tags, ids, name, denom_id, geom_id, timespan); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE TYPE cdb_dataservices_server.obs_meta_denominator AS (denom_id text, denom_name text, denom_description text, denom_weight text, denom_license text, denom_source text, denom_type text, denom_aggregate text, denom_extra jsonb, denom_tags jsonb, valid_numer boolean, valid_geom boolean, valid_timespan boolean); - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableDenominators( - username TEXT, - orgname TEXT, - bounds geometry(Geometry, 4326) DEFAULT NULL, - filter_tags TEXT[] DEFAULT NULL, - numer_id TEXT DEFAULT NULL, - geom_id TEXT DEFAULT NULL, - timespan TEXT DEFAULT NULL) -RETURNS SETOF cdb_dataservices_server.obs_meta_denominator AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetAvailableDenominators(bounds, filter_tags, numer_id, geom_id, timespan); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE TYPE cdb_dataservices_server.obs_meta_geometry AS (geom_id text, geom_name text, geom_description text, geom_weight text, geom_aggregate text, geom_license text, geom_source text, valid_numer boolean, valid_denom boolean, valid_timespan boolean, score numeric, numtiles bigint, notnull_percent numeric, numgeoms numeric, percentfill numeric, estnumgeoms numeric, meanmediansize numeric, geom_type text, geom_extra jsonb, geom_tags jsonb); - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableGeometries( - username TEXT, - orgname TEXT, - bounds geometry(Geometry, 4326) DEFAULT NULL, - filter_tags TEXT[] DEFAULT NULL, - numer_id TEXT DEFAULT NULL, - denom_id TEXT DEFAULT NULL, - timespan TEXT DEFAULT NULL, - number_geometries INTEGER DEFAULT NULL) -RETURNS SETOF cdb_dataservices_server.obs_meta_geometry AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetAvailableGeometries(bounds, filter_tags, numer_id, denom_id, timespan, number_geometries); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE TYPE cdb_dataservices_server.obs_meta_timespan AS (timespan_id text, timespan_name text, timespan_description text, timespan_weight text, timespan_aggregate text, timespan_license text, timespan_source text, valid_numer boolean, valid_denom boolean, valid_geom boolean, timespan_type text, timespan_extra jsonb, timespan_tags jsonb); - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableTimespans( - username TEXT, - orgname TEXT, - bounds geometry(Geometry, 4326) DEFAULT NULL, - filter_tags TEXT[] DEFAULT NULL, - numer_id TEXT DEFAULT NULL, - denom_id TEXT DEFAULT NULL, - geom_id TEXT DEFAULT NULL) -RETURNS SETOF cdb_dataservices_server.obs_meta_timespan AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_GetAvailableTimespans(bounds, filter_tags, numer_id, denom_id, geom_id); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_LegacyBuilderMetadata( - username TEXT, - orgname TEXT, - aggregate_type TEXT DEFAULT NULL) -RETURNS TABLE(name TEXT, subsection JSON) AS $$ - CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); - SELECT * FROM cdb_observatory.OBS_LegacyBuilderMetadata(aggregate_type); -$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; -CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_logger_config() -RETURNS boolean AS $$ - cache_key = "logger_config" - if cache_key in GD: - return False - else: - from cartodb_services.tools import LoggerConfig - logger_config = LoggerConfig(plpy) - GD[cache_key] = logger_config - return True -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - --- This is done in order to avoid an undesired depedency on cartodb extension -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_conf_getconf(input_key text) -RETURNS JSON AS $$ - SELECT VALUE FROM cartodb.cdb_conf WHERE key = input_key; -$$ LANGUAGE SQL SECURITY DEFINER STABLE PARALLEL SAFE; - -CREATE OR REPLACE -FUNCTION cdb_dataservices_server.CDB_Conf_SetConf(key text, value JSON) - RETURNS void AS $$ -BEGIN - PERFORM cdb_dataservices_server.CDB_Conf_RemoveConf(key); - EXECUTE 'INSERT INTO cartodb.CDB_CONF (KEY, VALUE) VALUES ($1, $2);' USING key, value; -END -$$ LANGUAGE PLPGSQL SECURITY DEFINER VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE -FUNCTION cdb_dataservices_server.CDB_Conf_RemoveConf(key text) - RETURNS void AS $$ -BEGIN - EXECUTE 'DELETE FROM cartodb.CDB_CONF WHERE KEY = $1;' USING key; -END -$$ LANGUAGE PLPGSQL SECURITY DEFINER VOLATILE PARALLEL UNSAFE ; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_geocoder_config(username text, orgname text, provider text DEFAULT NULL) -RETURNS boolean AS $$ - cache_key = "user_geocoder_config_{0}".format(username) - if cache_key in GD: - return False - else: - 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'] - geocoder_config = GeocoderConfig(redis_conn, plpy, username, orgname, provider) - GD[cache_key] = geocoder_config - return True -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_internal_geocoder_config(username text, orgname text) -RETURNS boolean AS $$ - cache_key = "user_internal_geocoder_config_{0}".format(username) - if cache_key in GD: - return False - else: - from cartodb_services.metrics import InternalGeocoderConfig - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection'] - geocoder_config = InternalGeocoderConfig(redis_conn, plpy, username, orgname) - GD[cache_key] = geocoder_config - return True -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -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: - 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'] - isolines_routing_config = IsolinesRoutingConfig(redis_conn, plpy, username, orgname) - GD[cache_key] = isolines_routing_config - return True -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -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: - 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'] - routing_config = RoutingConfig(redis_conn, plpy, username, orgname) - GD[cache_key] = routing_config - return True -$$ LANGUAGE plpythonu SECURITY DEFINER; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_obs_config(username text, orgname text) -RETURNS boolean AS $$ - cache_key = "user_obs_config_{0}".format(username) - if cache_key in GD: - return False - else: - from cartodb_services.metrics import ObservatoryConfig - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection'] - obs_config = ObservatoryConfig(redis_conn, plpy, username, orgname) - GD[cache_key] = obs_config - return True -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; -DO $$ -BEGIN - IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid) - WHERE pg_type.typname = 'service_type' - AND pg_namespace.nspname = 'cdb_dataservices_server') THEN - CREATE TYPE cdb_dataservices_server.service_type AS ENUM ( - 'isolines', - 'hires_geocoder', - 'routing', - 'observatory' - ); - END IF; -END $$; - -DO $$ -BEGIN - IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid) - WHERE pg_type.typname = 'service_quota_info' - AND pg_namespace.nspname = 'cdb_dataservices_server') THEN - CREATE TYPE cdb_dataservices_server.service_quota_info AS ( - service cdb_dataservices_server.service_type, - monthly_quota NUMERIC, - used_quota NUMERIC, - soft_limit BOOLEAN, - provider TEXT - ); - END IF; -END $$; - -DO $$ -BEGIN - IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid) - WHERE pg_type.typname = 'service_quota_info_batch' - AND pg_namespace.nspname = 'cdb_dataservices_server') THEN - CREATE TYPE cdb_dataservices_server.service_quota_info_batch AS ( - service cdb_dataservices_server.service_type, - monthly_quota NUMERIC, - used_quota NUMERIC, - soft_limit BOOLEAN, - provider TEXT, - max_batch_size NUMERIC - ); - END IF; -END $$; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info( - username TEXT, - orgname TEXT) -RETURNS SETOF cdb_dataservices_server.service_quota_info AS $$ - from cartodb_services.metrics.user import UserMetricsService - from datetime import date - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - - today = date.today() - ret = [] - - #-- Isolines - service = 'isolines' - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - user_service = UserMetricsService(user_isolines_config, redis_conn) - - monthly_quota = user_isolines_config.isolines_quota - used_quota = user_service.used_quota(user_isolines_config.service_type, today) - soft_limit = user_isolines_config.soft_isolines_limit - provider = user_isolines_config.provider - ret += [[service, monthly_quota, used_quota, soft_limit, provider]] - - #-- Hires Geocoder - service = 'hires_geocoder' - plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] - user_service = UserMetricsService(user_geocoder_config, redis_conn) - - monthly_quota = user_geocoder_config.geocoding_quota - used_quota = user_service.used_quota(user_geocoder_config.service_type, today) - soft_limit = user_geocoder_config.soft_geocoding_limit - provider = user_geocoder_config.provider - ret += [[service, monthly_quota, used_quota, soft_limit, provider]] - - #-- Routing - service = 'routing' - 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)] - user_service = UserMetricsService(user_routing_config, redis_conn) - - monthly_quota = user_routing_config.monthly_quota - used_quota = user_service.used_quota(user_routing_config.service_type, today) - soft_limit = user_routing_config.soft_limit - provider = user_routing_config.provider - ret += [[service, monthly_quota, used_quota, soft_limit, provider]] - - #-- Observatory - service = 'observatory' - plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_obs_config = GD["user_obs_config_{0}".format(username)] - user_service = UserMetricsService(user_obs_config, redis_conn) - - monthly_quota = user_obs_config.monthly_quota - used_quota = user_service.used_quota(user_obs_config.service_type, today) - soft_limit = user_obs_config.soft_limit - provider = user_obs_config.provider - ret += [[service, monthly_quota, used_quota, soft_limit, provider]] - - return ret -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info_batch( - username TEXT, - orgname TEXT) -RETURNS SETOF cdb_dataservices_server.service_quota_info_batch AS $$ - from cartodb_services.bulk_geocoders import BATCH_GEOCODER_CLASS_BY_PROVIDER - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - sqi = plpy.execute("SELECT * from cdb_dataservices_server.cdb_service_quota_info({0},{1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - - ret = [] - for info in sqi: - if info['service'] == 'hires_geocoder': - provider = info['provider'] - batch_geocoder_class = BATCH_GEOCODER_CLASS_BY_PROVIDER.get(provider, None) - if batch_geocoder_class and hasattr(batch_geocoder_class, 'MAX_BATCH_SIZE'): - max_batch_size = batch_geocoder_class.MAX_BATCH_SIZE - else: - max_batch_size = 1 - - info['max_batch_size'] = max_batch_size - else: - info['max_batch_size'] = 1 - - ret += [[info['service'], info['monthly_quota'], info['used_quota'], info['soft_limit'], info['provider'], info['max_batch_size']]] - - return ret -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_enough_quota( - username TEXT, - orgname TEXT, - service_ TEXT, - input_size NUMERIC) -returns BOOLEAN AS $$ - DECLARE - params cdb_dataservices_server.service_quota_info; - BEGIN - SELECT * INTO params - FROM cdb_dataservices_server.cdb_service_quota_info(username, orgname) AS p - WHERE p.service = service_::cdb_dataservices_server.service_type; - RETURN params.soft_limit OR ((params.used_quota + input_size) <= params.monthly_quota); - END -$$ LANGUAGE plpgsql STABLE PARALLEL RESTRICTED; --- Geocodes a street address given a searchtext and a state and/or country - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger,LoggerConfig - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - params = {'username': username, 'orgname': orgname, 'searchtext': searchtext, 'city': city, 'state_province': state_province, 'country': country} - - with metrics('cdb_geocode_street_point', user_geocoder_config, logger, params): - if user_geocoder_config.heremaps_geocoder: - here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - elif user_geocoder_config.google_geocoder: - google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - elif user_geocoder_config.mapzen_geocoder: - mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - elif user_geocoder_config.mapbox_geocoder: - mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - elif user_geocoder_config.tomtom_geocoder: - tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - elif user_geocoder_config.geocodio_geocoder: - geocodio_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocodio_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(geocodio_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - else: - raise Exception('Requested geocoder is not available') - -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_here_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] - - if user_geocoder_config.heremaps_geocoder: - here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - else: - raise Exception('Here geocoder is not available for your account.') - -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_google_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] - - if user_geocoder_config.google_geocoder: - google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - else: - raise Exception('Google geocoder is not available for your account.') - -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - # The configuration is retrieved but no checks are performed on it - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] - - mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - # The configuration is retrieved but no checks are performed on it - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] - - mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - # The configuration is retrieved but no checks are performed on it - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] - - tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocodio_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - # The configuration is retrieved but no checks are performed on it - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] - - geocodio_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocodio_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) - return plpy.execute(geocodio_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] - -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - from cartodb_services.tools import LegacyServiceManager - from cartodb_services.tools import QuotaExceededException - from cartodb_services.here import HereMapsGeocoder - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - service_manager = LegacyServiceManager('geocoder', username, orgname, GD) - - try: - service_manager.assert_within_limits() - geocoder = HereMapsGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params) - coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country) - if coordinates: - service_manager.quota_service.increment_success_service_use() - plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) - point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] - return point['st_setsrid'] - else: - service_manager.quota_service.increment_empty_service_use() - return None - except QuotaExceededException as qe: - service_manager.quota_service.increment_failed_service_use() - return None - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to geocode street point using here maps', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode street point using here maps') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_google_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - from cartodb_services.tools import LegacyServiceManager, QuotaExceededException - from cartodb_services.google import GoogleMapsGeocoder - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - service_manager = LegacyServiceManager('geocoder', username, orgname, GD) - - try: - service_manager.assert_within_limits(quota=False) - geocoder = GoogleMapsGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger) - coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country) - if coordinates: - service_manager.quota_service.increment_success_service_use() - plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) - point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] - return point['st_setsrid'] - else: - service_manager.quota_service.increment_empty_service_use() - return None - except QuotaExceededException as qe: - service_manager.quota_service.increment_failed_service_use() - return None - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to geocode street point using google maps', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode street point using google maps') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - from cartodb_services.tools import ServiceManager, QuotaExceededException - from cartodb_services.mapzen import MapzenGeocoder - from cartodb_services.tools.country import country_to_iso3 - from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname) - - try: - service_manager.assert_within_limits() - geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params) - country_iso3 = None - if country: - country_iso3 = country_to_iso3(country) - coordinates = geocoder.geocode(searchtext=searchtext, city=city, - state_province=state_province, - country=country_iso3, search_type='address') - if coordinates: - service_manager.quota_service.increment_success_service_use() - plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) - point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] - return point['st_setsrid'] - else: - service_manager.quota_service.increment_empty_service_use() - return None - except QuotaExceededException as qe: - service_manager.quota_service.increment_failed_service_use() - return None - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to geocode street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode street point using mapzen') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - from iso3166 import countries - from cartodb_services.tools import ServiceManager, QuotaExceededException - from cartodb_services.mapbox import MapboxGeocoder - from cartodb_services.tools.country import country_to_iso3 - from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD) - - try: - service_manager.assert_within_limits() - geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - country_iso3166 = None - if country: - country_iso3 = country_to_iso3(country) - if country_iso3: - country_iso3166 = countries.get(country_iso3).alpha2.lower() - - coordinates = geocoder.geocode(searchtext=searchtext, city=city, - state_province=state_province, - country=country_iso3166) - if coordinates: - service_manager.quota_service.increment_success_service_use() - plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) - point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] - return point['st_setsrid'] - else: - service_manager.quota_service.increment_empty_service_use() - return None - except QuotaExceededException as qe: - service_manager.quota_service.increment_failed_service_use() - return None - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to geocode street point using Mapbox', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode street point using Mapbox') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - from iso3166 import countries - from cartodb_services.tools import ServiceManager, QuotaExceededException - from cartodb_services.tomtom import TomTomGeocoder - from cartodb_services.tools.country import country_to_iso3 - from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD) - - try: - service_manager.assert_within_limits() - geocoder = TomTomGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) - - country_iso3166 = None - if country: - country_iso3 = country_to_iso3(country) - if country_iso3: - country_iso3166 = countries.get(country_iso3).alpha2.lower() - - coordinates = geocoder.geocode(searchtext=searchtext, city=city, - state_province=state_province, - country=country_iso3166) - if coordinates: - service_manager.quota_service.increment_success_service_use() - plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) - point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] - return point['st_setsrid'] - else: - service_manager.quota_service.increment_empty_service_use() - return None - except QuotaExceededException as qe: - service_manager.quota_service.increment_failed_service_use() - return None - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to geocode street point using TomTom', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode street point using TomTom') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocodio_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) -RETURNS Geometry AS $$ - from iso3166 import countries - from cartodb_services.tools import ServiceManager, QuotaExceededException - from cartodb_services.geocodio import GeocodioGeocoder - from cartodb_services.tools.country import country_to_iso3 - from cartodb_services.refactor.service.geocodio_geocoder_config import GeocodioGeocoderConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('geocoder', GeocodioGeocoderConfigBuilder, username, orgname, GD) - - try: - service_manager.assert_within_limits() - geocoder = GeocodioGeocoder(service_manager.config.geocodio_api_key, service_manager.logger, service_manager.config.service_params) - - country_iso3166 = None - if country: - country_iso3 = country_to_iso3(country) - if country_iso3: - country_iso3166 = countries.get(country_iso3).alpha2.lower() - - coordinates = geocoder.geocode(searchtext=searchtext, city=city, - state_province=state_province, - country=country_iso3166) - if coordinates: - service_manager.quota_service.increment_success_service_use() - plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) - point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] - return point['st_setsrid'] - else: - service_manager.quota_service.increment_empty_service_use() - return None - except QuotaExceededException as qe: - service_manager.quota_service.increment_failed_service_use() - return None - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to geocode street point using Geocodio', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode street point using Geocodio') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_get_rate_limit( - username TEXT, - orgname TEXT, - service TEXT) -RETURNS JSON AS $$ - import json - from cartodb_services.config import ServiceConfiguration, RateLimitsConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_config = ServiceConfiguration(service, username, orgname) - rate_limit_config = RateLimitsConfigBuilder(service_config.server, service_config.user, service_config.org, service=service, username=username, orgname=orgname).get() - if rate_limit_config.is_limited(): - return json.dumps({'limit': rate_limit_config.limit, 'period': rate_limit_config.period}) - else: - return None -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_set_user_rate_limit( - username TEXT, - orgname TEXT, - service TEXT, - rate_limit_json JSON) -RETURNS VOID AS $$ - import json - from cartodb_services.config import RateLimitsConfig, RateLimitsConfigSetter - - import cartodb_services - cartodb_services.init(plpy, GD) - - config_setter = RateLimitsConfigSetter(service=service, username=username, orgname=orgname) - if rate_limit_json: - rate_limit = json.loads(rate_limit_json) - limit = rate_limit.get('limit', None) - period = rate_limit.get('period', None) - else: - limit = None - period = None - config = RateLimitsConfig(service=service, username=username, limit=limit, period=period) - config_setter.set_user_rate_limits(config) -$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_set_org_rate_limit( - username TEXT, - orgname TEXT, - service TEXT, - rate_limit_json JSON) -RETURNS VOID AS $$ - import json - from cartodb_services.config import RateLimitsConfig, RateLimitsConfigSetter - - import cartodb_services - cartodb_services.init(plpy, GD) - - config_setter = RateLimitsConfigSetter(service=service, username=username, orgname=orgname) - if rate_limit_json: - rate_limit = json.loads(rate_limit_json) - limit = rate_limit.get('limit', None) - period = rate_limit.get('period', None) - else: - limit = None - period = None - config = RateLimitsConfig(service=service, username=username, limit=limit, period=period) - config_setter.set_org_rate_limits(config) -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_set_server_rate_limit( - username TEXT, - orgname TEXT, - service TEXT, - rate_limit_json JSON) -RETURNS VOID AS $$ - import json - from cartodb_services.config import RateLimitsConfig, RateLimitsConfigSetter - - import cartodb_services - cartodb_services.init(plpy, GD) - - config_setter = RateLimitsConfigSetter(service=service, username=username, orgname=orgname) - if rate_limit_json: - rate_limit = json.loads(rate_limit_json) - limit = rate_limit.get('limit', None) - period = rate_limit.get('period', None) - else: - limit = None - period = None - config = RateLimitsConfig(service=service, username=username, limit=limit, period=period) - config_setter.set_server_rate_limits(config) -$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; --- TODO: could cartodb_id be replaced by rowid, maybe needing extra care for offset? -CREATE TYPE cdb_dataservices_server.geocoding AS ( - cartodb_id integer, - the_geom geometry(Point,4326), - metadata jsonb -); - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) -RETURNS SETOF cdb_dataservices_server.geocoding AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger - import json - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - - plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - params = {'username': username, 'orgname': orgname, 'searches': json.loads(searches)} - - with metrics('cdb_bulk_geocode_street_point', user_geocoder_config, logger, params): - if user_geocoder_config.google_geocoder: - provider_function = "_cdb_bulk_google_geocode_street_point"; - elif user_geocoder_config.heremaps_geocoder: - provider_function = "_cdb_bulk_heremaps_geocode_street_point"; - elif user_geocoder_config.tomtom_geocoder: - provider_function = "_cdb_bulk_tomtom_geocode_street_point"; - elif user_geocoder_config.mapbox_geocoder: - provider_function = "_cdb_bulk_mapbox_geocode_street_point"; - elif user_geocoder_config.geocodio_geocoder: - provider_function = "_cdb_bulk_geocodio_geocode_street_point"; - else: - raise Exception('Requested geocoder is not available') - - plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.{}($1, $2, $3); ".format(provider_function), ["text", "text", "jsonb"]) - return plpy.execute(plan, [username, orgname, searches]) - -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_google_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) -RETURNS SETOF cdb_dataservices_server.geocoding AS $$ - from cartodb_services import run_street_point_geocoder - from cartodb_services.tools import LegacyServiceManager - from cartodb_services.google import GoogleMapsBulkGeocoder - - service_manager = LegacyServiceManager('geocoder', username, orgname, GD) - geocoder = GoogleMapsBulkGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger) - return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_heremaps_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) -RETURNS SETOF cdb_dataservices_server.geocoding AS $$ - from cartodb_services import run_street_point_geocoder - from cartodb_services.tools import LegacyServiceManager - from cartodb_services.here import HereMapsBulkGeocoder - - service_manager = LegacyServiceManager('geocoder', username, orgname, GD) - geocoder = HereMapsBulkGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params) - return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_tomtom_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) -RETURNS SETOF cdb_dataservices_server.geocoding AS $$ - from cartodb_services import run_street_point_geocoder - from cartodb_services.tools import ServiceManager - from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder - from cartodb_services.tomtom import TomTomBulkGeocoder - from cartodb_services.tools import Logger - import cartodb_services - cartodb_services.init(plpy, GD) - - logger_config = GD["logger_config"] - logger = Logger(logger_config) - service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD) - geocoder = TomTomBulkGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) - return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_mapbox_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) -RETURNS SETOF cdb_dataservices_server.geocoding AS $$ - from cartodb_services import run_street_point_geocoder - from cartodb_services.tools import ServiceManager - from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder - from cartodb_services.mapbox import MapboxBulkGeocoder - from cartodb_services.tools import Logger - import cartodb_services - cartodb_services.init(plpy, GD) - - logger_config = GD["logger_config"] - logger = Logger(logger_config) - service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD) - geocoder = MapboxBulkGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocodio_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) -RETURNS SETOF cdb_dataservices_server.geocoding AS $$ - from cartodb_services import run_street_point_geocoder - from cartodb_services.tools import ServiceManager - from cartodb_services.refactor.service.geocodio_geocoder_config import GeocodioGeocoderConfigBuilder - from cartodb_services.geocodio import GeocodioBulkGeocoder - from cartodb_services.tools import Logger - import cartodb_services - cartodb_services.init(plpy, GD) - - logger_config = GD["logger_config"] - logger = Logger(logger_config) - service_manager = ServiceManager('geocoder', GeocodioGeocoderConfigBuilder, username, orgname, GD) - geocoder = GeocodioBulkGeocoder(service_manager.config.geocodio_api_key, service_manager.logger, service_manager.config.service_params) - return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin0_polygon(username text, orgname text, country_name text) -RETURNS Geometry AS $$ - from cartodb_services.metrics import QuotaService - from cartodb_services.metrics import InternalGeocoderConfig - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_geocoder_config, redis_conn) - - params = {'username': username, 'orgname': orgname, 'country_name': country_name} - - with metrics('cdb_geocode_admin0_polygon', user_geocoder_config, logger, params): - try: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin0_polygon(trim($1)) AS mypolygon", ["text"]) - rv = plpy.execute(plan, [country_name], 1) - result = rv[0]["mypolygon"] - if result: - quota_service.increment_success_service_use() - return result - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to geocode admin0 polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode admin0 polygon') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - - --------------------------------------------------------------------------------- - --- Implementation of the server extension --- Note: these functions depend on the cdb_geocoder extension -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_admin0_polygon(country_name text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - SELECT n.the_geom as geom INTO ret - FROM (SELECT q, lower(regexp_replace(q, '[^a-zA-Z\u00C0-\u00ff]+', '', 'g'))::text x - FROM (SELECT country_name q) g) d - LEFT OUTER JOIN admin0_synonyms s ON name_ = d.x - LEFT OUTER JOIN ne_admin0_v3 n ON s.adm0_a3 = n.adm0_a3 GROUP BY d.q, n.the_geom, s.adm0_a3; - - RETURN ret; - END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; ----- cdb_geocode_admin1_polygon(admin1_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin1_polygon(username text, orgname text, admin1_name text) -RETURNS Geometry AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.metrics import InternalGeocoderConfig - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_geocoder_config, redis_conn) - - params = {'username': username, 'orgname': orgname, 'admin1_name': admin1_name} - - with metrics('cdb_geocode_admin1_polygon', user_geocoder_config, logger, params): - try: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1)) AS mypolygon", ["text"]) - rv = plpy.execute(plan, [admin1_name], 1) - result = rv[0]["mypolygon"] - if result: - quota_service.increment_success_service_use() - return result - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to geocode admin1 polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode admin1 polygon') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - ----- cdb_geocode_admin1_polygon(admin1_name text, country_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin1_polygon(username text, orgname text, admin1_name text, country_name text) -RETURNS Geometry AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.metrics import InternalGeocoderConfig - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_geocoder_config, redis_conn) - - with metrics('cdb_geocode_admin1_polygon', user_geocoder_config, logger): - try: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1), trim($2)) AS mypolygon", ["text", "text"]) - rv = plpy.execute(plan, [admin1_name, country_name], 1) - result = rv[0]["mypolygon"] - if result: - quota_service.increment_success_service_use() - return result - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to geocode admin1 polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode admin1 polygon') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --------------------------------------------------------------------------------- - --- Implementation of the server extension --- Note: these functions depend on the cdb_geocoder extension - ----- cdb_geocode_admin1_polygon(admin1_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_admin1_polygon(admin1_name text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - SELECT geom INTO ret - FROM ( - SELECT q, ( - SELECT the_geom - FROM global_province_polygons - WHERE d.c = ANY (synonyms) - ORDER BY frequency DESC LIMIT 1 - ) geom - FROM ( - SELECT - trim(replace(lower(admin1_name),'.',' ')) c, admin1_name q - ) d - ) v; - - RETURN ret; - END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; - ----- cdb_geocode_admin1_polygon(admin1_name text, country_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_admin1_polygon(admin1_name text, country_name text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - WITH p AS (SELECT r.c, r.q, (SELECT iso3 FROM country_decoder WHERE lower(country_name) = ANY (synonyms)) i FROM (SELECT trim(replace(lower(admin1_name),'.',' ')) c, country_name q) r) - SELECT - geom INTO ret - FROM ( - SELECT - q, ( - SELECT the_geom - FROM global_province_polygons - WHERE p.c = ANY (synonyms) - AND iso3 = p.i - ORDER BY frequency DESC LIMIT 1 - ) geom - FROM p) n; - - RETURN ret; - END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; - ----- cdb_geocode_namedplace_point(city_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text) -RETURNS Geometry AS $$ - import spiexceptions - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - try: - street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3) as point;", ["text", "text", "text"]) - return plpy.execute(street_point, [username, orgname, city_name])[0]['point'] - except spiexceptions.ExternalRoutineException as e: - import sys - logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname}) - internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3) as point;", ["text", "text", "text"]) - return plpy.execute(internal_plan, [username, orgname, city_name])[0]['point'] -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - ----- cdb_geocode_namedplace_point(city_name text, country_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, country_name text) -RETURNS Geometry AS $$ - import spiexceptions - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - try: - street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, NULL, $4) as point;", ["text", "text", "text", "text"]) - return plpy.execute(street_point, [username, orgname, city_name, country_name])[0]['point'] - except spiexceptions.ExternalRoutineException as e: - import sys - logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname}) - internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, NULL, $4) as point;", ["text", "text", "text", "text"]) - return plpy.execute(internal_plan, [username, orgname, city_name, country_name])[0]['point'] -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - ----- cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, admin1_name text, country_name text) -RETURNS Geometry AS $$ - import spiexceptions - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - try: - street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, $4, $5) as point;", ["text", "text", "text", "text", "text"]) - return plpy.execute(street_point, [username, orgname, city_name, admin1_name, country_name])[0]['point'] - except spiexceptions.ExternalRoutineException as e: - import sys - logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname}) - internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, $4, $5) as point;", ["text", "text", "text", "text", "text"]) - return plpy.execute(internal_plan, [username, orgname, city_name, admin1_name, country_name])[0]['point'] -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_internal_geocode_namedplace(username text, orgname text, city_name text, admin1_name text DEFAULT NULL, country_name text DEFAULT NULL) -RETURNS Geometry AS $$ - from cartodb_services.metrics import QuotaService - from cartodb_services.metrics import InternalGeocoderConfig, metrics - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_geocoder_config, redis_conn) - - params = {'username': username, 'orgname': orgname, 'city_name': city_name, 'admin1_name': admin1_name, 'country_name': country_name} - - with metrics('cdb_geocode_namedplace_point', user_geocoder_config, logger, params): - try: - if admin1_name and country_name: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2), trim($3)) AS mypoint", ["text", "text", "text"]) - rv = plpy.execute(plan, [city_name, admin1_name, country_name], 1) - elif country_name: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2)) AS mypoint", ["text", "text"]) - rv = plpy.execute(plan, [city_name, country_name], 1) - else: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1)) AS mypoint", ["text"]) - rv = plpy.execute(plan, [city_name], 1) - result = rv[0]["mypoint"] - if result: - quota_service.increment_success_service_use() - return result - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to geocode namedplace point', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode namedplace point') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --------------------------------------------------------------------------------- - --- Implementation of the server extension --- Note: these functions depend on the cdb_geocoder extension - ----- cdb_geocode_namedplace_point(city_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_namedplace_point(city_name text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - SELECT geom INTO ret - FROM ( - WITH best AS (SELECT s AS q, (SELECT the_geom FROM global_cities_points_limited gp WHERE gp.lowername = lower(p.s) ORDER BY population DESC LIMIT 1) AS geom FROM (SELECT city_name as s) p), - next AS (SELECT p.s AS q, (SELECT gp.the_geom FROM global_cities_points_limited gp, global_cities_alternates_limited ga WHERE lower(p.s) = ga.lowername AND ga.geoname_id = gp.geoname_id ORDER BY preferred DESC LIMIT 1) geom FROM (SELECT city_name as s) p WHERE p.s NOT IN (SELECT q FROM best WHERE geom IS NOT NULL)) - SELECT q, geom, TRUE AS success FROM best WHERE geom IS NOT NULL - UNION ALL - SELECT q, geom, CASE WHEN geom IS NULL THEN FALSE ELSE TRUE END AS success FROM next - ) v; - - RETURN ret; - END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; - ----- cdb_geocode_namedplace_point(city_name text, country_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_namedplace_point(city_name text, country_name text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - SELECT geom INTO ret - FROM ( - WITH p AS (SELECT r.s, r.c, (SELECT iso2 FROM country_decoder WHERE lower(r.c) = ANY (synonyms)) i FROM (SELECT city_name AS s, country_name::text AS c) r), - best AS (SELECT p.s AS q, p.c AS c, (SELECT gp.the_geom AS geom FROM global_cities_points_limited gp WHERE gp.lowername = lower(p.s) AND gp.iso2 = p.i ORDER BY population DESC LIMIT 1) AS geom FROM p), - next AS (SELECT p.s AS q, p.c AS c, (SELECT gp.the_geom FROM global_cities_points_limited gp, global_cities_alternates_limited ga WHERE lower(p.s) = ga.lowername AND gp.iso2 = p.i AND ga.geoname_id = gp.geoname_id ORDER BY preferred DESC LIMIT 1) geom FROM p WHERE p.s NOT IN (SELECT q FROM best WHERE c = p.c AND geom IS NOT NULL)) - SELECT geom FROM best WHERE geom IS NOT NULL - UNION ALL - SELECT geom FROM next - ) v; - - RETURN ret; - END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; - ----- cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - SELECT geom INTO ret - FROM ( - WITH inputcountry AS ( - SELECT iso2 as isoTwo FROM country_decoder WHERE lower(country_name) = ANY (synonyms) LIMIT 1 - ), - p AS ( - SELECT r.s, r.a1, (SELECT admin1 FROM admin1_decoder, inputcountry WHERE lower(r.a1) = ANY (synonyms) AND admin1_decoder.iso2 = inputcountry.isoTwo LIMIT 1) i FROM (SELECT city_name AS s, admin1_name::text AS a1) r), - best AS (SELECT p.s AS q, p.a1 as a1, (SELECT gp.the_geom AS geom FROM global_cities_points_limited gp WHERE gp.lowername = lower(p.s) AND gp.admin1 = p.i ORDER BY population DESC LIMIT 1) AS geom FROM p), - next AS (SELECT p.s AS q, p.a1 AS a1, (SELECT gp.the_geom FROM global_cities_points_limited gp, global_cities_alternates_limited ga WHERE lower(p.s) = ga.lowername AND ga.admin1 = p.i AND ga.geoname_id = gp.geoname_id ORDER BY preferred DESC LIMIT 1) geom FROM p WHERE p.s NOT IN (SELECT q FROM best WHERE geom IS NOT NULL)) - SELECT geom FROM best WHERE geom IS NOT NULL - UNION ALL - SELECT geom FROM next - ) v; - - RETURN ret; - END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code text) -RETURNS Geometry AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.metrics import InternalGeocoderConfig - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_geocoder_config, redis_conn) - - params = {'username': username, 'orgname': orgname, 'code': code} - - with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger, params): - try: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1)) AS mypoint", ["text"]) - rv = plpy.execute(plan, [code], 1) - result = rv[0]["mypoint"] - if result: - quota_service.increment_success_service_use() - return result - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode postal code point') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code double precision) -RETURNS Geometry AS $$ - SELECT cdb_dataservices_server.cdb_geocode_postalcode_point(username, orgname, code::text); -$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code text, country text) -RETURNS Geometry AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.metrics import InternalGeocoderConfig - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_geocoder_config, redis_conn) - with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger): - try: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1), trim($2)) AS mypoint", ["TEXT", "TEXT"]) - rv = plpy.execute(plan, [code, country], 1) - result = rv[0]["mypoint"] - if result: - quota_service.increment_success_service_use() - return result - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode postal code point') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code double precision, country text) -RETURNS Geometry AS $$ - SELECT cdb_dataservices_server.cdb_geocode_postalcode_point(username, orgname, code::text, country); -$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code text) -RETURNS Geometry AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.metrics import InternalGeocoderConfig - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_geocoder_config, redis_conn) - with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger): - try: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1)) AS mypolygon", ["text"]) - rv = plpy.execute(plan, [code], 1) - result = rv[0]["mypolygon"] - if result: - quota_service.increment_success_service_use() - return result - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode postal code polygon') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code double precision) -RETURNS Geometry AS $$ - SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon(username, orgname, code::text) -$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; - - - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code text, country text) -RETURNS Geometry AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.metrics import InternalGeocoderConfig - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_geocoder_config, redis_conn) - with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger): - try: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1), trim($2)) AS mypolygon", ["TEXT", "TEXT"]) - rv = plpy.execute(plan, [code, country], 1) - result = rv[0]["mypolygon"] - if result: - quota_service.increment_success_service_use() - return result - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode postal code polygon') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code double precision, country text) -RETURNS Geometry AS $$ - SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon(username, orgname, code::text, country); -$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; - --------------------------------------------------------------------------------- - --- Implementation of the server extension --- Note: these functions depend on the cdb_geocoder extension -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_point(code text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - SELECT geom INTO ret - FROM ( - SELECT - q, ( - SELECT the_geom - FROM global_postal_code_points - WHERE postal_code = upper(d.q) - LIMIT 1 - ) geom - FROM (SELECT code q) d - ) v; - - RETURN ret; -END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_point(code text, country text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - SELECT geom INTO ret - FROM ( - SELECT - q, ( - SELECT the_geom - FROM global_postal_code_points - WHERE postal_code = upper(d.q) - AND iso3 = ( - SELECT iso3 FROM country_decoder WHERE - lower(country) = ANY (synonyms) LIMIT 1 - ) - LIMIT 1 - ) geom - FROM (SELECT code q) d - ) v; - - RETURN ret; -END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_polygon(code text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - SELECT geom INTO ret - FROM ( - SELECT - q, ( - SELECT the_geom - FROM global_postal_code_polygons - WHERE postal_code = upper(d.q) - LIMIT 1 - ) geom - FROM (SELECT code q) d - ) v; - - RETURN ret; -END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_polygon(code text, country text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - BEGIN - SELECT geom INTO ret - FROM ( - SELECT - q, ( - SELECT the_geom - FROM global_postal_code_polygons - WHERE postal_code = upper(d.q) - AND iso3 = ( - SELECT iso3 FROM country_decoder WHERE - lower(country) = ANY (synonyms) LIMIT 1 - ) - LIMIT 1 - ) geom - FROM (SELECT code q) d - ) v; - - RETURN ret; -END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_ipaddress_point(username text, orgname text, ip text) -RETURNS Geometry AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.metrics import QuotaService - from cartodb_services.metrics import InternalGeocoderConfig - from cartodb_services.tools import Logger,LoggerConfig - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_geocoder_config, redis_conn) - - params = {'username': username, 'orgname': orgname, 'ip': ip} - - with metrics('cdb_geocode_ipaddress_point', user_geocoder_config, logger): - try: - plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_ipaddress_point(trim($1)) AS mypoint", ["TEXT"]) - rv = plpy.execute(plan, [ip], 1) - result = rv[0]["mypoint"] - if result: - quota_service.increment_success_service_use() - return result - else: - quota_service.increment_empty_service_use() - return None - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to geocode postal code polygon') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --------------------------------------------------------------------------------- - --- Implementation of the server extension --- Note: these functions depend on the cdb_geocoder extension -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_ipaddress_point(ip text) -RETURNS Geometry AS $$ - DECLARE - ret Geometry; - - new_ip INET; - BEGIN - BEGIN - IF family(ip::inet) = 6 THEN - new_ip := ip::inet; - ELSE - new_ip := ('::ffff:' || ip)::inet; - END IF; - EXCEPTION WHEN OTHERS THEN - SELECT NULL as geom INTO ret; - RETURN ret; - END; - - WITH - ips AS (SELECT ip s, new_ip net), - matches AS (SELECT s, (SELECT the_geom FROM ip_address_locations WHERE network_start_ip <= ips.net ORDER BY network_start_ip DESC LIMIT 1) geom FROM ips) - SELECT geom INTO ret - FROM matches; - RETURN ret; -END -$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; -CREATE TYPE cdb_dataservices_server.isoline AS (center geometry(Geometry,4326), data_range integer, the_geom geometry(Multipolygon,4326)); - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_routing_isolines(username TEXT, orgname TEXT, type TEXT, source geometry(Geometry, 4326), mode TEXT, data_range integer[], options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - import json - from cartodb_services.here import HereMapsRoutingIsoline - from cartodb_services.metrics import QuotaService - from cartodb_services.here.types import geo_polyline_to_multipolygon - from cartodb_services.tools import Logger,LoggerConfig - - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - # -- Check the quota - quota_service = QuotaService(user_isolines_routing_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - try: - client = HereMapsRoutingIsoline(user_isolines_routing_config.heremaps_app_id, - user_isolines_routing_config.heremaps_app_code, logger) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - source_str = 'geo!%f,%f' % (lat, lon) - else: - source_str = None - - if type == 'isodistance': - resp = client.calculate_isodistance(source_str, mode, data_range, options) - elif type == 'isochrone': - resp = client.calculate_isochrone(source_str, mode, data_range, options) - - if resp: - result = [] - for isoline in resp: - data_range_n = isoline['range'] - polyline = isoline['geom'] - multipolygon = geo_polyline_to_multipolygon(polyline) - result.append([source, data_range_n, multipolygon]) - quota_service.increment_success_service_use() - quota_service.increment_isolines_service_use(len(resp)) - return result - else: - quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get mapzen isolines') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isodistance( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - import json - from cartodb_services.mapzen import MatrixClient, MapzenIsolines - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - quota_service = QuotaService(user_isolines_routing_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - try: - client = MatrixClient(user_isolines_routing_config.mapzen_matrix_api_key, logger, user_isolines_routing_config.mapzen_matrix_service_params) - mapzen_isolines = MapzenIsolines(client, logger) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = {'lat': lat, 'lon': lon} - else: - raise Exception('source is NULL') - - # -- TODO Support options properly - isolines = {} - for r in data_range: - isoline = mapzen_isolines.calculate_isodistance(origin, mode, r) - isolines[r] = isoline - - result = [] - for r in data_range: - - if len(isolines[r]) >= 3: - # -- TODO encapsulate this block into a func/method - locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point - wkt_coordinates = ','.join(["%f %f" % (l['lon'], l['lat']) for l in locations]) - sql = "SELECT ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326) as geom".format(wkt_coordinates) - multipolygon = plpy.execute(sql, 1)[0]['geom'] - else: - multipolygon = None - - result.append([source, r, multipolygon]) - - quota_service.increment_success_service_use() - quota_service.increment_isolines_service_use(len(isolines)) - return result - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get mapzen isolines') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - # -- TODO Support options properly - isolines = {} - for r in data_range: - isoline = mapbox_isolines.calculate_isodistance(origin, r, profile) - isolines[r] = isoline - - result = [] - for r in data_range: - - if len(isolines[r]) >= 3: - # -- TODO encapsulate this block into a func/method - locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point - wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) - sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) - multipolygon = plpy.execute(sql, 1)[0]['geom'] - else: - multipolygon = None - - result.append([source, r, multipolygon]) - - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(isolines)) - return result - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox isolines') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.tomtom import TomTomIsolines - from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM - from cartodb_services.tools import Coordinate - from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_TOMTOM.get(mode) - - # -- TODO Support options properly - isolines = {} - for r in data_range: - isoline = tomtom_isolines.calculate_isodistance(origin, r, profile) - isolines[r] = isoline - - result = [] - for r in data_range: - - if len(isolines[r]) >= 3: - # -- TODO encapsulate this block into a func/method - locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point - wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) - sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) - multipolygon = plpy.execute(sql, 1)[0]['geom'] - else: - multipolygon = None - - result.append([source, r, multipolygon]) - - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(isolines)) - return result - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get TomTom isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get TomTom isolines') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - import json - from cartodb_services.mapzen import MatrixClient, MapzenIsochrones - from cartodb_services.metrics import QuotaService - from cartodb_services.tools import Logger,LoggerConfig - from cartodb_services.mapzen.types import coordinates_to_polygon - - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)] - - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - # -- Check the quota - quota_service = QuotaService(user_isolines_routing_config, redis_conn) - if not quota_service.check_user_quota(): - raise Exception('You have reached the limit of your quota') - - try: - mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key, - logger, user_isolines_routing_config.mapzen_isochrones_service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = {'lat': lat, 'lon': lon} - else: - raise Exception('source is NULL') - - resp = mapzen_isochrones.isochrone(origin, mode, data_range) - - if resp: - result = [] - for isochrone in resp: - result_polygon = coordinates_to_polygon(isochrone.coordinates) - if result_polygon: - result.append([source, isochrone.duration, result_polygon]) - else: - result.append([source, isochrone.duration, None]) - quota_service.increment_success_service_use() - quota_service.increment_isolines_service_use(len(result)) - return result - else: - quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - quota_service.increment_failed_service_use() - logger.error('Error trying to get mapzen isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get mapzen isochrones') - finally: - quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.mapbox import MapboxIsolines - from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX - from cartodb_services.tools import Coordinate - from cartodb_services.tools.coordinates import coordinates_to_polygon - from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) - - resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile) - - if resp: - result = [] - for isochrone in resp: - result_polygon = coordinates_to_polygon(isochrone.coordinates) - if result_polygon: - result.append([source, isochrone.duration, result_polygon]) - else: - result.append([source, isochrone.duration, None]) - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(result)) - return result - else: - service_manager.quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get Mapbox isochrones') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones( - username TEXT, - orgname TEXT, - source geometry(Geometry, 4326), - mode TEXT, - data_range integer[], - options text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.tools import ServiceManager - from cartodb_services.tomtom import TomTomIsolines - from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM - from cartodb_services.tools import Coordinate - from cartodb_services.tools.coordinates import coordinates_to_polygon - from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder - - import cartodb_services - cartodb_services.init(plpy, GD) - - service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD) - service_manager.assert_within_limits() - - try: - tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) - - if source: - lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] - lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] - origin = Coordinate(lon,lat) - else: - raise Exception('source is NULL') - - profile = TRANSPORT_MODE_TO_TOMTOM.get(mode) - - resp = tomtom_isolines.calculate_isochrone(origin, data_range, profile) - - if resp: - result = [] - for isochrone in resp: - result_polygon = coordinates_to_polygon(isochrone.coordinates) - if result_polygon: - result.append([source, isochrone.duration, result_polygon]) - else: - result.append([source, isochrone.duration, None]) - service_manager.quota_service.increment_success_service_use() - service_manager.quota_service.increment_isolines_service_use(len(result)) - return result - else: - service_manager.quota_service.increment_empty_service_use() - return [] - except BaseException as e: - import sys - service_manager.quota_service.increment_failed_service_use() - service_manager.logger.error('Error trying to get TomTom isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) - raise Exception('Error trying to get TomTom isochrones') - finally: - service_manager.quota_service.increment_total_service_use() -$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - if user_isolines_config.google_services_user: - raise Exception('This service is not available for google service users.') - - params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} - - with metrics('cdb_isodistance', user_isolines_config, logger, params): - if user_isolines_config.heremaps_provider: - here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapzen_provider: - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_provider: - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.tomtom_provider: - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) - else: - raise Exception('Requested isolines provider is not available') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --- heremaps isodistance -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_here_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - type = 'isodistance' - - here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(here_plan, [username, orgname, type, source, mode, range, options]) - - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --- mapzen isodistance -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) - - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --- mapbox isodistance -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --- tomtom isodistance -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) - - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - from cartodb_services.metrics import metrics - from cartodb_services.tools import Logger - - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") - logger_config = GD["logger_config"] - logger = Logger(logger_config) - - if user_isolines_config.google_services_user: - raise Exception('This service is not available for google service users.') - - params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} - - with metrics('cdb_isochrone', user_isolines_config, logger, params): - if user_isolines_config.heremaps_provider: - here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapzen_provider: - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.mapbox_provider: - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - elif user_isolines_config.tomtom_provider: - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) - else: - raise Exception('Requested isolines provider is not available') -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --- heremaps isochrone -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_here_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - type = 'isochrone' - - here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(here_plan, [username, orgname, type, source, mode, range, options]) - - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --- mapzen isochrone -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --- mapbox isochrone -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; - --- tomtom isochrone -CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) -RETURNS SETOF cdb_dataservices_server.isoline AS $$ - plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) - redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] - plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) - user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] - - tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) - result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) - return result -$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; -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$$; From ef5b82450aa6da2421364f9baa26350f42be0aea Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Tue, 11 Feb 2020 15:25:12 +0100 Subject: [PATCH 18/20] Avoid renaming the matrix parameter to isolines --- README.md | 2 +- .../test/expected/00_install_test.out | 2 +- server/extension/test/sql/00_install_test.sql | 2 +- .../cartodb_services/mapbox/isolines.py | 4 +- .../cartodb_services/metrics/config.py | 43 ++++++++++++------- .../service/mapbox_isolines_config.py | 7 ++- .../cartodb_services/test/test_helper.py | 2 +- 7 files changed, 39 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index faa6ef5..72be30b 100644 --- a/README.md +++ b/README.md @@ -167,7 +167,7 @@ SELECT CDB_Conf_SetConf( ```sql SELECT CDB_Conf_SetConf( 'mapbox_conf', - '{"routing": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "geocoder": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "isolines": {"api_keys": ["your_api_key"], "monthly_quota": 1500000}}' + '{"routing": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "geocoder": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "matrix": {"api_keys": ["your_api_key"], "monthly_quota": 1500000}}' ); ``` diff --git a/server/extension/test/expected/00_install_test.out b/server/extension/test/expected/00_install_test.out index 43c6941..016e70c 100644 --- a/server/extension/test/expected/00_install_test.out +++ b/server/extension/test/expected/00_install_test.out @@ -33,7 +33,7 @@ SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"routing": {"api_key": "routing (1 row) -SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["isolines_dummy_api_key"], "monthly_quota": 1500000}}'); +SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); cdb_conf_setconf ------------------ diff --git a/server/extension/test/sql/00_install_test.sql b/server/extension/test/sql/00_install_test.sql index 2a4ef6b..a5c3652 100644 --- a/server/extension/test/sql/00_install_test.sql +++ b/server/extension/test/sql/00_install_test.sql @@ -15,7 +15,7 @@ SELECT cartodb.cdb_conf_setconf('redis_metrics_config', '{"redis_host": "localho SELECT cartodb.cdb_conf_setconf('redis_metadata_config', '{"redis_host": "localhost", "redis_port": 6379, "timeout": 0.1, "redis_db": 5}'); SELECT cartodb.cdb_conf_setconf('heremaps_conf', '{"geocoder": {"app_id": "dummy_id", "app_code": "dummy_code", "geocoder_cost_per_hit": 1}, "isolines": {"app_id": "dummy_id", "app_code": "dummy_code"}}'); SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"routing": {"api_key": "routing_dummy_api_key", "monthly_quota": 1500000}, "geocoder": {"api_key": "geocoder_dummy_api_key", "monthly_quota": 1500000}, "matrix": {"api_key": "matrix_dummy_api_key", "monthly_quota": 1500000}}'); -SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["isolines_dummy_api_key"], "monthly_quota": 1500000}}'); +SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}'); SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["isolines_dummy_api_key"], "monthly_quota": 1500000}}'); SELECT cartodb.cdb_conf_setconf('geocodio_conf', '{"geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}}'); SELECT cartodb.cdb_conf_setconf('logger_conf', '{"geocoder_log_path": "/dev/null"}'); diff --git a/server/lib/python/cartodb_services/cartodb_services/mapbox/isolines.py b/server/lib/python/cartodb_services/cartodb_services/mapbox/isolines.py index f3056e7..700c62b 100644 --- a/server/lib/python/cartodb_services/cartodb_services/mapbox/isolines.py +++ b/server/lib/python/cartodb_services/cartodb_services/mapbox/isolines.py @@ -22,9 +22,9 @@ MAX_SPEEDS = { PROFILE_DRIVING: 38.89 # In m/s, assuming 140km/h max speed } -VALID_PROFILES = [PROFILE_DRIVING, +VALID_PROFILES = (PROFILE_DRIVING, PROFILE_CYCLING, - PROFILE_WALKING] + PROFILE_WALKING) ENTRY_FEATURES = 'features' ENTRY_GEOMETRY = 'geometry' diff --git a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py index dc7625d..68c9a9c 100644 --- a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py +++ b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py @@ -255,8 +255,9 @@ class IsolinesRoutingConfig(ServiceConfig): self._mapzen_matrix_service_params = db_config.mapzen_matrix_service_params self._mapzen_isochrones_service_params = db_config.mapzen_isochrones_service_params elif self._isolines_provider == self.MAPBOX_PROVIDER: - self._mapbox_isolinesx_api_keys = self._db_config.mapbox_isolines_api_keys - self._mapbox_isolines_service_params = db_config.mapbox_isolines_service_params + self._mapbox_matrix_api_key = self._db_config.mapbox_matrix_api_key + self._mapbox_matrix_service_params = db_config.mapbox_matrix_service_params + self._mapbox_isochrones_service_params = db_config.mapbox_isochrones_service_params elif self._isolines_provider == self.TOMTOM_PROVIDER: self._tomtom_isolinesx_api_keys = self._db_config.tomtom_isolines_api_keys self._tomtom_isolines_service_params = db_config.tomtom_isolines_service_params @@ -317,12 +318,16 @@ class IsolinesRoutingConfig(ServiceConfig): return self._isolines_provider == self.MAPZEN_PROVIDER @property - def mapbox_isolines_api_keys(self): - return self._mapbox_isolines_api_keys + def mapbox_matrix_api_key(self): + return self._mapbox_matrix_api_key @property - def mapbox_isolines_service_params(self): - return self._mapbox_isolines_service_params + def mapbox_matrix_service_params(self): + return self._mapbox_matrix_service_params + + @property + def mapbox_isochrones_service_params(self): + return self._mapbox_isochrones_service_params @property def mapbox_provider(self): @@ -671,9 +676,13 @@ class ServicesDBConfig: raise ConfigException('Mapbox configuration missing') mapbox_conf = json.loads(mapbox_conf_json) - self._mapbox_isolines_api_keys = mapbox_conf['isolines']['api_keys'] - self._mapbox_isolines_quota = mapbox_conf['isolines']['monthly_quota'] - self._mapbox_isolines_service_params = mapbox_conf.get('isolines', {}).get('service', {}) + + # Note: We are no longer using the Matrix API but we have avoided renaming the `matrix` parameter + # to `isolines` to ensure retrocompatibility + self._mapbox_matrix_api_key = mapbox_conf['matrix']['api_key'] + self._mapbox_matrix_quota = mapbox_conf['matrix']['monthly_quota'] + self._mapbox_matrix_service_params = mapbox_conf['matrix'].get('service', {}) + self._mapbox_isochrones_service_params = mapbox_conf.get('isochrones', {}).get('service', {}) self._mapbox_routing_api_keys = mapbox_conf['routing']['api_keys'] self._mapbox_routing_quota = mapbox_conf['routing']['monthly_quota'] self._mapbox_routing_service_params = mapbox_conf['routing'].get('service', {}) @@ -801,16 +810,20 @@ class ServicesDBConfig: return self._mapzen_geocoder_service_params @property - def mapbox_isolines_api_keys(self): - return self._mapbox_isolines_api_keys + def mapbox_matrix_api_keys(self): + return self._mapbox_matrix_api_keys @property - def mapbox_isolines_monthly_quota(self): - return self._mapbox_isolines_quota + def mapbox_matrix_monthly_quota(self): + return self._mapbox_matrix_quota @property - def mapbox_isolines_service_params(self): - return self._mapbox_isolines_service_params + def mapbox_matrix_service_params(self): + return self._mapbox_matrix_service_params + + @property + def mapbox_isochrones_service_params(self): + return self._mapbox_isochrones_service_params @property def mapbox_routing_api_keys(self): diff --git a/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_isolines_config.py b/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_isolines_config.py index 5a252e9..b65707c 100644 --- a/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_isolines_config.py +++ b/server/lib/python/cartodb_services/cartodb_services/refactor/service/mapbox_isolines_config.py @@ -92,8 +92,11 @@ class MapboxIsolinesConfigBuilder(object): def get(self): mapbox_server_conf = self._server_conf.get('mapbox_conf') - mapbox_api_keys = mapbox_server_conf['isolines']['api_keys'] - mapbox_service_params = mapbox_server_conf['isolines'].get('service', {}) + + # Note: We are no longer using the Matrix API but we have avoided renaming the `matrix` parameter + # to `isolines` to ensure retrocompatibility + mapbox_api_keys = mapbox_server_conf['matrix']['api_keys'] + mapbox_service_params = mapbox_server_conf['matrix'].get('service', {}) isolines_quota = self._get_quota() soft_isolines_limit = self._user_conf.get('soft_here_isolines_limit').lower() == 'true' diff --git a/server/lib/python/cartodb_services/test/test_helper.py b/server/lib/python/cartodb_services/test/test_helper.py index 82bb84b..79ec6e2 100644 --- a/server/lib/python/cartodb_services/test/test_helper.py +++ b/server/lib/python/cartodb_services/test/test_helper.py @@ -76,7 +76,7 @@ def increment_service_uses(redis_conn, username, orgname=None, def plpy_mock_config(): plpy_mock._define_result("CDB_Conf_GetConf\('heremaps_conf'\)", [{'conf': '{"geocoder": {"app_id": "app_id", "app_code": "code", "geocoder_cost_per_hit": 1}, "isolines": {"app_id": "app_id", "app_code": "code"}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('mapzen_conf'\)", [{'conf': '{"routing": {"api_key": "api_key_rou", "monthly_quota": 1500000}, "geocoder": {"api_key": "api_key_geo", "monthly_quota": 1500000}, "matrix": {"api_key": "api_key_mat", "monthly_quota": 1500000}}'}]) - plpy_mock._define_result("CDB_Conf_GetConf\('mapbox_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) + plpy_mock._define_result("CDB_Conf_GetConf\('mapbox_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('tomtom_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('geocodio_conf'\)", [{'conf': '{"geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}}'}]) plpy_mock._define_result("CDB_Conf_GetConf\('logger_conf'\)", [{'conf': '{"geocoder_log_path": "/dev/null"}'}]) From 6081613220677bb079202b69c65a7c6af4c0d082 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Tue, 11 Feb 2020 15:29:35 +0100 Subject: [PATCH 19/20] Added autogenerated files --- ...db_dataservices_server--0.36.0--0.37.0.sql | 126 + ...db_dataservices_server--0.37.0--0.36.0.sql | 129 + .../cdb_dataservices_server--0.37.0.sql | 3886 +++++++++++++++++ ...db_dataservices_server--0.35.1--0.36.0.sql | 0 ...db_dataservices_server--0.36.0--0.35.1.sql | 0 .../cdb_dataservices_server--0.36.0.sql | 0 6 files changed, 4141 insertions(+) create mode 100644 server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql create mode 100644 server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql create mode 100644 server/extension/cdb_dataservices_server--0.37.0.sql rename server/extension/{ => old_versions}/cdb_dataservices_server--0.35.1--0.36.0.sql (100%) rename server/extension/{ => old_versions}/cdb_dataservices_server--0.36.0--0.35.1.sql (100%) rename server/extension/{ => old_versions}/cdb_dataservices_server--0.36.0.sql (100%) diff --git a/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql b/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql new file mode 100644 index 0000000..43609ac --- /dev/null +++ b/server/extension/cdb_dataservices_server--0.36.0--0.37.0.sql @@ -0,0 +1,126 @@ +-- Complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.37.0'" to load this file. \quit + +-- HERE goes your code to upgrade/downgrade + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapbox_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; diff --git a/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql b/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql new file mode 100644 index 0000000..3124830 --- /dev/null +++ b/server/extension/cdb_dataservices_server--0.37.0--0.36.0.sql @@ -0,0 +1,129 @@ +-- Complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.36.0'" to load this file. \quit + +-- HERE goes your code to upgrade/downgrade + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + mapbox_isolines = MapboxIsolines(client, service_manager.logger) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapbox_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + mapbox_isolines = MapboxIsolines(client, service_manager.logger) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; diff --git a/server/extension/cdb_dataservices_server--0.37.0.sql b/server/extension/cdb_dataservices_server--0.37.0.sql new file mode 100644 index 0000000..b8fb460 --- /dev/null +++ b/server/extension/cdb_dataservices_server--0.37.0.sql @@ -0,0 +1,3886 @@ +--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_server" to load this file. \quit +CREATE TYPE cdb_dataservices_server.simple_route AS ( + shape geometry(LineString,4326), + length real, + duration integer +); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_route_with_waypoints( + username TEXT, + orgname TEXT, + waypoints geometry(Point, 4326)[], + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxRouting + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.polyline import polyline_to_linestring + from cartodb_services.tools.normalize import options_to_dict + from cartodb_services.refactor.service.mapbox_routing_config import MapboxRoutingConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('routing', MapboxRoutingConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + client = MapboxRouting(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if not waypoints or len(waypoints) < 2: + service_manager.logger.info("Empty origin or destination") + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + + if len(waypoints) > 25: + service_manager.logger.info("Too many waypoints (max 25)") + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + + waypoint_coords = [] + for waypoint in waypoints: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon'] + waypoint_coords.append(Coordinate(lon,lat)) + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + options_dict = options_to_dict(options) + if 'mode_type' in options_dict: + plpy.warning('Mapbox provider doesnt support route type parameter') + + resp = client.directions(waypoint_coords, profile) + if resp and resp.shape: + shape_linestring = polyline_to_linestring(resp.shape) + if shape_linestring: + service_manager.quota_service.increment_success_service_use() + return [shape_linestring, resp.length, int(round(resp.duration))] + else: + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + else: + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to calculate Mapbox routing', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to calculate Mapbox routing') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoints( + username TEXT, + orgname TEXT, + waypoints geometry(Point, 4326)[], + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.tomtom import TomTomRouting + from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM, DEFAULT_ROUTE_TYPE, MODE_TYPE_TO_TOMTOM + from cartodb_services.tools import Coordinate + from cartodb_services.tools.polyline import polyline_to_linestring + from cartodb_services.tools.normalize import options_to_dict + from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('routing', TomTomRoutingConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + client = TomTomRouting(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + + if not waypoints or len(waypoints) < 2: + service_manager.logger.info("Empty origin or destination") + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + + if len(waypoints) > 25: + service_manager.logger.info("Too many waypoints (max 25)") + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + + waypoint_coords = [] + for waypoint in waypoints: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon'] + waypoint_coords.append(Coordinate(lon,lat)) + + profile = TRANSPORT_MODE_TO_TOMTOM.get(mode) + route_type = DEFAULT_ROUTE_TYPE + options_dict = options_to_dict(options) + if 'mode_type' in options_dict: + route_type = MODE_TYPE_TO_TOMTOM.get(options_dict['mode_type']) + + resp = client.directions(waypoint_coords, profile=profile, route_type=route_type) + if resp and resp.shape: + shape_linestring = polyline_to_linestring(resp.shape) + if shape_linestring: + service_manager.quota_service.increment_success_service_use() + return [shape_linestring, resp.length, int(round(resp.duration))] + else: + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + else: + service_manager.quota_service.increment_empty_service_use() + return [None, None, None] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to calculate TomTom routing', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to calculate TomTom routing') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_route_with_waypoints( + username TEXT, + orgname TEXT, + waypoints geometry(Point, 4326)[], + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + import json + from cartodb_services.mapzen import MapzenRouting, MapzenRoutingResponse + from cartodb_services.mapzen.types import polyline_to_linestring + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Coordinate + from cartodb_services.tools import Logger,LoggerConfig + + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + user_routing_config = GD["user_routing_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + quota_service = QuotaService(user_routing_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + try: + client = MapzenRouting(user_routing_config.mapzen_api_key, logger, user_routing_config.mapzen_service_params) + + if not waypoints or len(waypoints) < 2: + logger.info("Empty origin or destination") + quota_service.increment_empty_service_use() + return [None, None, None] + + waypoint_coords = [] + for waypoint in waypoints: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon'] + waypoint_coords.append(Coordinate(lon,lat)) + + resp = client.calculate_route_point_to_point(waypoint_coords, mode, options, units) + if resp and resp.shape: + shape_linestring = polyline_to_linestring(resp.shape) + if shape_linestring: + quota_service.increment_success_service_use() + return [shape_linestring, resp.length, resp.duration] + else: + quota_service.increment_empty_service_use() + return [None, None, None] + else: + quota_service.increment_empty_service_use() + return [None, None, None] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to calculate mapzen routing', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to calculate mapzen routing') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point( + username TEXT, + orgname TEXT, + origin geometry(Point, 4326), + destination geometry(Point, 4326), + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_routing_config = GD["user_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + params = {'username': username, 'orgname': orgname, 'origin': origin, 'destination': destination, 'mode': mode, 'options': options, 'units': units} + + with metrics('cdb_route_with_point', user_routing_config, logger, params): + waypoints = [origin, destination] + + if user_routing_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + elif user_routing_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + elif user_routing_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + else: + raise Exception('Requested routing method is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints( + username TEXT, + orgname TEXT, + waypoints geometry(Point, 4326)[], + mode TEXT, + options text[] DEFAULT ARRAY[]::text[], + units text DEFAULT 'kilometers') +RETURNS cdb_dataservices_server.simple_route AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_routing_config = GD["user_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + params = {'username': username, 'orgname': orgname, 'waypoints': waypoints, 'mode': mode, 'options': options, 'units': units} + + with metrics('cdb_route_with_waypoints', user_routing_config, logger, params): + if user_routing_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + elif user_routing_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + elif user_routing_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"]) + result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units]) + return [result[0]['shape'],result[0]['length'], result[0]['duration']] + else: + raise Exception('Requested routing method is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +-- 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, RedisDBConfig + metadata_config = RedisDBConfig('redis_metadata_config', plpy) + metrics_config = RedisDBConfig('redis_metrics_config', plpy) + redis_metadata_connection = RedisConnection(metadata_config).redis_connection() + redis_metrics_connection = RedisConnection(metrics_config).redis_connection() + GD[cache_key] = { + 'redis_metadata_connection': redis_metadata_connection, + 'redis_metrics_connection': redis_metrics_connection, + } + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +-- +-- Observatory connection config +-- +-- The purpose of this function is provide to the PL/Proxy functions +-- the connection string needed to connect with the current production database + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._obs_server_conn_str( + username TEXT, + orgname TEXT) +RETURNS text 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_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + return user_obs_config.connection_str +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetDemographicSnapshotJSON( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL, + geometry_level TEXT DEFAULT NULL) +RETURNS json AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetDemographicSnapshot(geom, time_span, geometry_level); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_get_demographic_snapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL, + geometry_level TEXT DEFAULT NULL) +RETURNS json AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + import json + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getdemographicsnapshot', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshotJSON($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level]) + if result: + quota_service.increment_success_service_use() + return result[0]['snapshot'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to obs_get_demographic_snapshot') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetDemographicSnapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL, + geometry_level TEXT DEFAULT NULL) +RETURNS SETOF json AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetDemographicSnapshot(geom, time_span, geometry_level); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetDemographicSnapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL, + geometry_level TEXT DEFAULT NULL) +RETURNS SETOF JSON AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getdemographicsnapshot', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshot($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level]) + if result: + resp = [] + for element in result: + value = element['snapshot'] + resp.append(value) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to obs_get_demographic_snapshot') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetSegmentSnapshotJSON( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + geometry_level TEXT DEFAULT NULL) +RETURNS json AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetSegmentSnapshot(geom, geometry_level); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_get_segment_snapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + geometry_level TEXT DEFAULT NULL) +RETURNS json AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + import json + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getsegmentsnapshot', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetSegmentSnapshotJSON($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level]) + if result: + quota_service.increment_success_service_use() + return result[0]['snapshot'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to obs_get_segment_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to obs_get_segment_snapshot') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetSegmentSnapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + geometry_level TEXT DEFAULT NULL) +RETURNS SETOF json AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetSegmentSnapshot(geom, geometry_level); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetSegmentSnapshot( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + geometry_level TEXT DEFAULT NULL) +RETURNS SETOF JSON AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getsegmentsnapshot', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetSegmentSnapshot($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level]) + if result: + resp = [] + for element in result: + value = element['snapshot'] + resp.append(value) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetSegmentSnapshot', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetSegmentSnapshot') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeasure( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + measure_id TEXT, + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetMeasure(geom, measure_id, normalize, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeasure( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + measure_id TEXT, + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getmeasure', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasure($1, $2, $3, $4, $5, $6, $7) as measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, measure_id, normalize, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['measure'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetMeasure', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetMeasure') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetCategory( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + category_id TEXT, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetCategory(geom, category_id, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetCategory( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + category_id TEXT, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getcategory', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetCategory($1, $2, $3, $4, $5, $6) as category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, category_id, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['category'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetCategory', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetCategory') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetUSCensusMeasure( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + name TEXT, + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetUSCensusMeasure(geom, name, normalize, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetUSCensusMeasure( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + name TEXT, + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getuscensusmeasure', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusMeasure($1, $2, $3, $4, $5, $6, $7) as census_measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, name, normalize, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['census_measure'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetUSCensusMeasure', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetUSCensusMeasure') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetUSCensusCategory( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + name TEXT, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetUSCensusCategory(geom, name, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetUSCensusCategory( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + name TEXT, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getuscensuscategory', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusCategory($1, $2, $3, $4, $5, $6) as census_category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, name, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['census_category'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetUSCensusCategory', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetUSCensusCategory') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPopulation( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetPopulation(geom, normalize, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPopulation( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + normalize TEXT DEFAULT NULL, + boundary_id TEXT DEFAULT NULL, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getpopulation', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetPopulation($1, $2, $3, $4, $5, $6) as population;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, normalize, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['population'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetPopulation', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetPopulation') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeasureById( + username TEXT, + orgname TEXT, + geom_ref TEXT, + measure_id TEXT, + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetMeasureById(geom_ref, measure_id, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeasureById( + username TEXT, + orgname TEXT, + geom_ref TEXT, + measure_id TEXT, + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS NUMERIC AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getmeasurebyid', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasureById($1, $2, $3, $4, $5, $6) as measure;", ["text", "text", "text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom_ref, measure_id, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['measure'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetMeasureById') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData( + username TEXT, + orgname TEXT, + geomvals geomval[], + params JSON, + merge BOOLEAN DEFAULT True) +RETURNS TABLE ( + id INT, + data JSON +) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetData(geomvals, params, merge); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData( + username TEXT, + orgname TEXT, + geomvals geomval[], + params JSON, + merge BOOLEAN DEFAULT True) +RETURNS TABLE ( + id INT, + data JSON +) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getdata', user_obs_config, logger, params): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4, $5);", ["text", "text", "geomval[]", "json", "boolean"]) + result = plpy.execute(obs_plan, [username, orgname, geomvals, params, merge]) + empty_results = len(geomvals) - len(result) + if empty_results > 0: + quota_service.increment_empty_service_use(empty_results) + if result: + quota_service.increment_success_service_use(len(result)) + return result + else: + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use(len(geomvals)) + logger.error('Error trying to OBS_GetData', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetData') + finally: + quota_service.increment_total_service_use(len(geomvals)) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData( + username TEXT, + orgname TEXT, + geomrefs TEXT[], + params JSON) +RETURNS TABLE ( + id TEXT, + data JSON +) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetData(geomrefs, params); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData( + username TEXT, + orgname TEXT, + geomrefs TEXT[], + params JSON) +RETURNS TABLE ( + id TEXT, + data JSON +) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getdata', user_obs_config, logger, params): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4);", ["text", "text", "text[]", "json"]) + result = plpy.execute(obs_plan, [username, orgname, geomrefs, params]) + empty_results = len(geomrefs) - len(result) + if empty_results > 0: + quota_service.increment_empty_service_use(empty_results) + if result: + quota_service.increment_success_service_use(len(result)) + return result + else: + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use(len(geomrefs)) + exc_info = sys.exc_info() + logger.error('%s, %s, %s' % (exc_info[0], exc_info[1], exc_info[2])) + logger.error('Error trying to OBS_GetData', exc_info, data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetData') + finally: + quota_service.increment_total_service_use(len(geomrefs)) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeta( + username TEXT, + orgname TEXT, + geom Geometry(Geometry, 4326), + params JSON, + max_timespan_rank INTEGER DEFAULT NULL, + max_score_rank INTEGER DEFAULT NULL, + target_geoms INTEGER DEFAULT NULL) +RETURNS JSON AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetMeta(geom, params, max_timespan_rank, max_score_rank, target_geoms); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeta( + username TEXT, + orgname TEXT, + geom Geometry(Geometry, 4326), + params JSON, + max_timespan_rank INTEGER DEFAULT NULL, + max_score_rank INTEGER DEFAULT NULL, + target_geoms INTEGER DEFAULT NULL) +RETURNS JSON AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + with metrics('obs_getmeta', user_obs_config, logger, params): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeta($1, $2, $3, $4, $5, $6, $7) as meta;", ["text", "text", "Geometry (Geometry, 4326)", "json", "integer", "integer", "integer"]) + result = plpy.execute(obs_plan, [username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms]) + if result: + return result[0]['meta'] + else: + return None + except BaseException as e: + import sys + logger.error('Error trying to OBS_GetMeta', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetMeta') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_MetadataValidation( + username TEXT, + orgname TEXT, + geometry_extent Geometry(Geometry, 4326), + geometry_type text, + params JSON, + target_geoms INTEGER DEFAULT NULL) +RETURNS TABLE(valid boolean, errors text[]) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_MetadataValidation(geometry_extent, geometry_type, params, target_geoms); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_MetadataValidation( + username TEXT, + orgname TEXT, + geometry_extent Geometry(Geometry, 4326), + geometry_type text, + params JSON, + target_geoms INTEGER DEFAULT NULL) +RETURNS TABLE(valid boolean, errors text[]) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + with metrics('obs_metadatavalidation', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_MetadataValidation($1, $2, $3, $4, $5, $6);", ["text", "text", "Geometry (Geometry, 4326)", "text", "json", "integer"]) + result = plpy.execute(obs_plan, [username, orgname, geometry_extent, geometry_type, params, target_geoms]) + if result: + return result + else: + return [] + except BaseException as e: + import sys + logger.error('Error trying to OBS_MetadataValidation', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_MetadataValidation') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_Search( + username TEXT, + orgname TEXT, + search_term TEXT, + relevant_boundary TEXT DEFAULT NULL) +RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_Search(search_term, relevant_boundary); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_Search( + username TEXT, + orgname TEXT, + search_term TEXT, + relevant_boundary TEXT DEFAULT NULL) +RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_search', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_Search($1, $2, $3, $4);", ["text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, search_term, relevant_boundary]) + if result: + resp = [] + for element in result: + id = element['id'] + description = element['description'] + name = element['name'] + aggregate = element['aggregate'] + source = element['source'] + resp.append([id, description, name, aggregate, source]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [None, None, None, None, None] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_Search', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_Search') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetAvailableBoundaries( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL) +RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableBoundaries(geom, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableBoundaries( + username TEXT, + orgname TEXT, + geom geometry(Geometry, 4326), + time_span TEXT DEFAULT NULL) +RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getavailableboundaries', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetAvailableBoundaries($1, $2, $3, $4) as available_boundaries;", ["text", "text", "geometry(Geometry, 4326)", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, time_span]) + if result: + resp = [] + for element in result: + id = element['boundary_id'] + description = element['description'] + tspan = element['time_span'] + tablename = element['tablename'] + resp.append([id, description, tspan, tablename]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetMeasureById') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundary( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS geometry(Geometry, 4326) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetBoundary(geom, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundary( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS geometry(Geometry, 4326) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundary', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundary($1, $2, $3, $4) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['boundary'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundary', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundary') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundaryId( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetBoundaryId(geom, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundaryId( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS TEXT AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundaryid', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryId($1, $2, $3, $4, $5) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['boundary'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundaryId', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundaryId') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundaryById( + username TEXT, + orgname TEXT, + geometry_id TEXT, + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS geometry(Geometry, 4326) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.OBS_GetBoundaryById(geometry_id, boundary_id, time_span); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundaryById( + username TEXT, + orgname TEXT, + geometry_id TEXT, + boundary_id TEXT, + time_span TEXT DEFAULT NULL) +RETURNS geometry(Geometry, 4326) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundarybyid', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryById($1, $2, $3, $4, $5) as boundary;", ["text", "text", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geometry_id, boundary_id, time_span]) + if result: + quota_service.increment_success_service_use() + return result[0]['boundary'] + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundaryById', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundaryById') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundariesByGeometry( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type text DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetBoundariesByGeometry(geom, boundary_id, time_span, overlap_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundariesByGeometry( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundariesbygeometry', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type]) + if result: + resp = [] + for element in result: + the_geom = element['the_geom'] + geom_refs = element['geom_refs'] + resp.append([the_geom, geom_refs]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundariesByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundariesByGeometry') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundariesByPointAndRadius( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + radius NUMERIC, + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetBoundariesByPointAndRadius(geom, radius, boundary_id, time_span, overlap_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundariesByPointAndRadius( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + radius NUMERIC, + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getboundariesbypointandradius', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type]) + if result: + resp = [] + for element in result: + the_geom = element['the_geom'] + geom_refs = element['geom_refs'] + resp.append([the_geom, geom_refs]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetBoundariesByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetBoundariesByPointAndRadius') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPointsByGeometry( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetPointsByGeometry(geom, boundary_id, time_span, overlap_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPointsByGeometry( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getpointsbygeometry', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type]) + if result: + resp = [] + for element in result: + the_geom = element['the_geom'] + geom_refs = element['geom_refs'] + resp.append([the_geom, geom_refs]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetPointsByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetPointsByGeometry') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPointsByPointAndRadius( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + radius NUMERIC, + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetPointsByPointAndRadius(geom, radius, boundary_id, time_span, overlap_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPointsByPointAndRadius( + username TEXT, + orgname TEXT, + geom geometry(Point, 4326), + radius NUMERIC, + boundary_id TEXT, + time_span TEXT DEFAULT NULL, + overlap_type TEXT DEFAULT NULL) +RETURNS TABLE(the_geom geometry, geom_refs text) AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_obs_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + with metrics('obs_getpointsbypointandradius', user_obs_config, logger): + try: + obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"]) + result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type]) + if result: + resp = [] + for element in result: + the_geom = element['the_geom'] + geom_refs = element['geom_refs'] + resp.append([the_geom, geom_refs]) + quota_service.increment_success_service_use() + return resp + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to OBS_GetPointsByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to OBS_GetPointsByPointAndRadius') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE TYPE cdb_dataservices_server.ds_fdw_metadata as (schemaname text, tabname text, servername text); + +CREATE TYPE cdb_dataservices_server.ds_return_metadata as (colnames text[], coltypes text[]); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_ConnectUserTable(username text, orgname text, user_db_role text, input_schema text, dbname text, table_name text) +RETURNS cdb_dataservices_server.ds_fdw_metadata AS $$ + host_addr = plpy.execute("SELECT split_part(inet_client_addr()::text, '/', 1) as user_host")[0]['user_host'] + return plpy.execute("SELECT * FROM cdb_dataservices_server.__DST_ConnectUserTable({username}::text, {orgname}::text, {user_db_role}::text, {schema}::text, {dbname}::text, {host_addr}::text, {table_name}::text)" + .format(username=plpy.quote_nullable(username), orgname=plpy.quote_nullable(orgname), user_db_role=plpy.quote_literal(user_db_role), schema=plpy.quote_literal(input_schema), dbname=plpy.quote_literal(dbname), table_name=plpy.quote_literal(table_name), host_addr=plpy.quote_literal(host_addr)) + )[0] +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.__DST_ConnectUserTable(username text, orgname text, user_db_role text, input_schema text, dbname text, host_addr text, table_name text) +RETURNS cdb_dataservices_server.ds_fdw_metadata AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + TARGET cdb_observatory._OBS_ConnectUserTable; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_GetReturnMetadata(username text, orgname text, function_name text, params json) +RETURNS cdb_dataservices_server.ds_return_metadata AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + TARGET cdb_observatory._OBS_GetReturnMetadata; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_FetchJoinFdwTableData(username text, orgname text, table_schema text, table_name text, function_name text, params json) +RETURNS SETOF record AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + TARGET cdb_observatory._OBS_FetchJoinFdwTableData; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._DST_DisconnectUserTable(username text, orgname text, table_schema text, table_name text, servername text) +RETURNS boolean AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + TARGET cdb_observatory._OBS_DisconnectUserTable; +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_dumpversion(username text, orgname text) +RETURNS text AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT cdb_observatory.obs_dumpversion(); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +-- We could create a super type for the common data like id, name and so on but we need to parse inside the functions because the -- the return data tha comes from OBS is a TABLE() with them +CREATE TYPE cdb_dataservices_server.obs_meta_numerator AS (numer_id text, numer_name text, numer_description text, numer_weight text, numer_license text, numer_source text, numer_type text, numer_aggregate text, numer_extra jsonb, numer_tags jsonb, valid_denom boolean, valid_geom boolean, valid_timespan boolean); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableNumerators( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + filter_tags TEXT[] DEFAULT NULL, + denom_id TEXT DEFAULT NULL, + geom_id TEXT DEFAULT NULL, + timespan TEXT DEFAULT NULL) +RETURNS SETOF cdb_dataservices_server.obs_meta_numerator AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableNumerators(bounds, filter_tags, denom_id, geom_id, timespan); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetNumerators( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + section_tags TEXT[] DEFAULT ARRAY[]::TEXT[], + subsection_tags TEXT[] DEFAULT ARRAY[]::TEXT[], + other_tags TEXT[] DEFAULT ARRAY[]::TEXT[], + ids TEXT[] DEFAULT ARRAY[]::TEXT[], + name TEXT DEFAULT NULL, + denom_id TEXT DEFAULT '', + geom_id TEXT DEFAULT '', + timespan TEXT DEFAULT '') +RETURNS SETOF cdb_dataservices_server.obs_meta_numerator AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory._OBS_GetNumerators(bounds, section_tags, subsection_tags, other_tags, ids, name, denom_id, geom_id, timespan); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE TYPE cdb_dataservices_server.obs_meta_denominator AS (denom_id text, denom_name text, denom_description text, denom_weight text, denom_license text, denom_source text, denom_type text, denom_aggregate text, denom_extra jsonb, denom_tags jsonb, valid_numer boolean, valid_geom boolean, valid_timespan boolean); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableDenominators( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + filter_tags TEXT[] DEFAULT NULL, + numer_id TEXT DEFAULT NULL, + geom_id TEXT DEFAULT NULL, + timespan TEXT DEFAULT NULL) +RETURNS SETOF cdb_dataservices_server.obs_meta_denominator AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableDenominators(bounds, filter_tags, numer_id, geom_id, timespan); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE TYPE cdb_dataservices_server.obs_meta_geometry AS (geom_id text, geom_name text, geom_description text, geom_weight text, geom_aggregate text, geom_license text, geom_source text, valid_numer boolean, valid_denom boolean, valid_timespan boolean, score numeric, numtiles bigint, notnull_percent numeric, numgeoms numeric, percentfill numeric, estnumgeoms numeric, meanmediansize numeric, geom_type text, geom_extra jsonb, geom_tags jsonb); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableGeometries( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + filter_tags TEXT[] DEFAULT NULL, + numer_id TEXT DEFAULT NULL, + denom_id TEXT DEFAULT NULL, + timespan TEXT DEFAULT NULL, + number_geometries INTEGER DEFAULT NULL) +RETURNS SETOF cdb_dataservices_server.obs_meta_geometry AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableGeometries(bounds, filter_tags, numer_id, denom_id, timespan, number_geometries); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE TYPE cdb_dataservices_server.obs_meta_timespan AS (timespan_id text, timespan_name text, timespan_description text, timespan_weight text, timespan_aggregate text, timespan_license text, timespan_source text, valid_numer boolean, valid_denom boolean, valid_geom boolean, timespan_type text, timespan_extra jsonb, timespan_tags jsonb); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableTimespans( + username TEXT, + orgname TEXT, + bounds geometry(Geometry, 4326) DEFAULT NULL, + filter_tags TEXT[] DEFAULT NULL, + numer_id TEXT DEFAULT NULL, + denom_id TEXT DEFAULT NULL, + geom_id TEXT DEFAULT NULL) +RETURNS SETOF cdb_dataservices_server.obs_meta_timespan AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_GetAvailableTimespans(bounds, filter_tags, numer_id, denom_id, geom_id); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_LegacyBuilderMetadata( + username TEXT, + orgname TEXT, + aggregate_type TEXT DEFAULT NULL) +RETURNS TABLE(name TEXT, subsection JSON) AS $$ + CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname); + SELECT * FROM cdb_observatory.OBS_LegacyBuilderMetadata(aggregate_type); +$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE; +CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_logger_config() +RETURNS boolean AS $$ + cache_key = "logger_config" + if cache_key in GD: + return False + else: + from cartodb_services.tools import LoggerConfig + logger_config = LoggerConfig(plpy) + GD[cache_key] = logger_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +-- This is done in order to avoid an undesired depedency on cartodb extension +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_conf_getconf(input_key text) +RETURNS JSON AS $$ + SELECT VALUE FROM cartodb.cdb_conf WHERE key = input_key; +$$ LANGUAGE SQL SECURITY DEFINER STABLE PARALLEL SAFE; + +CREATE OR REPLACE +FUNCTION cdb_dataservices_server.CDB_Conf_SetConf(key text, value JSON) + RETURNS void AS $$ +BEGIN + PERFORM cdb_dataservices_server.CDB_Conf_RemoveConf(key); + EXECUTE 'INSERT INTO cartodb.CDB_CONF (KEY, VALUE) VALUES ($1, $2);' USING key, value; +END +$$ LANGUAGE PLPGSQL SECURITY DEFINER VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE +FUNCTION cdb_dataservices_server.CDB_Conf_RemoveConf(key text) + RETURNS void AS $$ +BEGIN + EXECUTE 'DELETE FROM cartodb.CDB_CONF WHERE KEY = $1;' USING key; +END +$$ LANGUAGE PLPGSQL SECURITY DEFINER VOLATILE PARALLEL UNSAFE ; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_geocoder_config(username text, orgname text, provider text DEFAULT NULL) +RETURNS boolean AS $$ + cache_key = "user_geocoder_config_{0}".format(username) + if cache_key in GD: + return False + else: + 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'] + geocoder_config = GeocoderConfig(redis_conn, plpy, username, orgname, provider) + GD[cache_key] = geocoder_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_internal_geocoder_config(username text, orgname text) +RETURNS boolean AS $$ + cache_key = "user_internal_geocoder_config_{0}".format(username) + if cache_key in GD: + return False + else: + from cartodb_services.metrics import InternalGeocoderConfig + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection'] + geocoder_config = InternalGeocoderConfig(redis_conn, plpy, username, orgname) + GD[cache_key] = geocoder_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +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: + 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'] + isolines_routing_config = IsolinesRoutingConfig(redis_conn, plpy, username, orgname) + GD[cache_key] = isolines_routing_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +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: + 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'] + routing_config = RoutingConfig(redis_conn, plpy, username, orgname) + GD[cache_key] = routing_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_obs_config(username text, orgname text) +RETURNS boolean AS $$ + cache_key = "user_obs_config_{0}".format(username) + if cache_key in GD: + return False + else: + from cartodb_services.metrics import ObservatoryConfig + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection'] + obs_config = ObservatoryConfig(redis_conn, plpy, username, orgname) + GD[cache_key] = obs_config + return True +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid) + WHERE pg_type.typname = 'service_type' + AND pg_namespace.nspname = 'cdb_dataservices_server') THEN + CREATE TYPE cdb_dataservices_server.service_type AS ENUM ( + 'isolines', + 'hires_geocoder', + 'routing', + 'observatory' + ); + END IF; +END $$; + +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid) + WHERE pg_type.typname = 'service_quota_info' + AND pg_namespace.nspname = 'cdb_dataservices_server') THEN + CREATE TYPE cdb_dataservices_server.service_quota_info AS ( + service cdb_dataservices_server.service_type, + monthly_quota NUMERIC, + used_quota NUMERIC, + soft_limit BOOLEAN, + provider TEXT + ); + END IF; +END $$; + +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid) + WHERE pg_type.typname = 'service_quota_info_batch' + AND pg_namespace.nspname = 'cdb_dataservices_server') THEN + CREATE TYPE cdb_dataservices_server.service_quota_info_batch AS ( + service cdb_dataservices_server.service_type, + monthly_quota NUMERIC, + used_quota NUMERIC, + soft_limit BOOLEAN, + provider TEXT, + max_batch_size NUMERIC + ); + END IF; +END $$; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info( + username TEXT, + orgname TEXT) +RETURNS SETOF cdb_dataservices_server.service_quota_info AS $$ + from cartodb_services.metrics.user import UserMetricsService + from datetime import date + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + + today = date.today() + ret = [] + + #-- Isolines + service = 'isolines' + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + user_service = UserMetricsService(user_isolines_config, redis_conn) + + monthly_quota = user_isolines_config.isolines_quota + used_quota = user_service.used_quota(user_isolines_config.service_type, today) + soft_limit = user_isolines_config.soft_isolines_limit + provider = user_isolines_config.provider + ret += [[service, monthly_quota, used_quota, soft_limit, provider]] + + #-- Hires Geocoder + service = 'hires_geocoder' + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + user_service = UserMetricsService(user_geocoder_config, redis_conn) + + monthly_quota = user_geocoder_config.geocoding_quota + used_quota = user_service.used_quota(user_geocoder_config.service_type, today) + soft_limit = user_geocoder_config.soft_geocoding_limit + provider = user_geocoder_config.provider + ret += [[service, monthly_quota, used_quota, soft_limit, provider]] + + #-- Routing + service = 'routing' + 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)] + user_service = UserMetricsService(user_routing_config, redis_conn) + + monthly_quota = user_routing_config.monthly_quota + used_quota = user_service.used_quota(user_routing_config.service_type, today) + soft_limit = user_routing_config.soft_limit + provider = user_routing_config.provider + ret += [[service, monthly_quota, used_quota, soft_limit, provider]] + + #-- Observatory + service = 'observatory' + plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_obs_config = GD["user_obs_config_{0}".format(username)] + user_service = UserMetricsService(user_obs_config, redis_conn) + + monthly_quota = user_obs_config.monthly_quota + used_quota = user_service.used_quota(user_obs_config.service_type, today) + soft_limit = user_obs_config.soft_limit + provider = user_obs_config.provider + ret += [[service, monthly_quota, used_quota, soft_limit, provider]] + + return ret +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info_batch( + username TEXT, + orgname TEXT) +RETURNS SETOF cdb_dataservices_server.service_quota_info_batch AS $$ + from cartodb_services.bulk_geocoders import BATCH_GEOCODER_CLASS_BY_PROVIDER + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + sqi = plpy.execute("SELECT * from cdb_dataservices_server.cdb_service_quota_info({0},{1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + + ret = [] + for info in sqi: + if info['service'] == 'hires_geocoder': + provider = info['provider'] + batch_geocoder_class = BATCH_GEOCODER_CLASS_BY_PROVIDER.get(provider, None) + if batch_geocoder_class and hasattr(batch_geocoder_class, 'MAX_BATCH_SIZE'): + max_batch_size = batch_geocoder_class.MAX_BATCH_SIZE + else: + max_batch_size = 1 + + info['max_batch_size'] = max_batch_size + else: + info['max_batch_size'] = 1 + + ret += [[info['service'], info['monthly_quota'], info['used_quota'], info['soft_limit'], info['provider'], info['max_batch_size']]] + + return ret +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_enough_quota( + username TEXT, + orgname TEXT, + service_ TEXT, + input_size NUMERIC) +returns BOOLEAN AS $$ + DECLARE + params cdb_dataservices_server.service_quota_info; + BEGIN + SELECT * INTO params + FROM cdb_dataservices_server.cdb_service_quota_info(username, orgname) AS p + WHERE p.service = service_::cdb_dataservices_server.service_type; + RETURN params.soft_limit OR ((params.used_quota + input_size) <= params.monthly_quota); + END +$$ LANGUAGE plpgsql STABLE PARALLEL RESTRICTED; +-- Geocodes a street address given a searchtext and a state and/or country + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger,LoggerConfig + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + params = {'username': username, 'orgname': orgname, 'searchtext': searchtext, 'city': city, 'state_province': state_province, 'country': country} + + with metrics('cdb_geocode_street_point', user_geocoder_config, logger, params): + if user_geocoder_config.heremaps_geocoder: + here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.google_geocoder: + google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.mapzen_geocoder: + mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.mapbox_geocoder: + mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.tomtom_geocoder: + tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + elif user_geocoder_config.geocodio_geocoder: + geocodio_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocodio_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(geocodio_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + else: + raise Exception('Requested geocoder is not available') + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_here_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + if user_geocoder_config.heremaps_geocoder: + here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + else: + raise Exception('Here geocoder is not available for your account.') + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_google_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + if user_geocoder_config.google_geocoder: + google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + else: + raise Exception('Google geocoder is not available for your account.') + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + # The configuration is retrieved but no checks are performed on it + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + # The configuration is retrieved but no checks are performed on it + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + # The configuration is retrieved but no checks are performed on it + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocodio_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + # The configuration is retrieved but no checks are performed on it + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + geocodio_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocodio_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"]) + return plpy.execute(geocodio_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point'] + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.tools import LegacyServiceManager + from cartodb_services.tools import QuotaExceededException + from cartodb_services.here import HereMapsGeocoder + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + service_manager = LegacyServiceManager('geocoder', username, orgname, GD) + + try: + service_manager.assert_within_limits() + geocoder = HereMapsGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params) + coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using here maps', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using here maps') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_google_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.tools import LegacyServiceManager, QuotaExceededException + from cartodb_services.google import GoogleMapsGeocoder + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + service_manager = LegacyServiceManager('geocoder', username, orgname, GD) + + try: + service_manager.assert_within_limits(quota=False) + geocoder = GoogleMapsGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger) + coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using google maps', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using google maps') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.tools import ServiceManager, QuotaExceededException + from cartodb_services.mapzen import MapzenGeocoder + from cartodb_services.tools.country import country_to_iso3 + from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname) + + try: + service_manager.assert_within_limits() + geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params) + country_iso3 = None + if country: + country_iso3 = country_to_iso3(country) + coordinates = geocoder.geocode(searchtext=searchtext, city=city, + state_province=state_province, + country=country_iso3, search_type='address') + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using mapzen') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from iso3166 import countries + from cartodb_services.tools import ServiceManager, QuotaExceededException + from cartodb_services.mapbox import MapboxGeocoder + from cartodb_services.tools.country import country_to_iso3 + from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD) + + try: + service_manager.assert_within_limits() + geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + country_iso3166 = None + if country: + country_iso3 = country_to_iso3(country) + if country_iso3: + country_iso3166 = countries.get(country_iso3).alpha2.lower() + + coordinates = geocoder.geocode(searchtext=searchtext, city=city, + state_province=state_province, + country=country_iso3166) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using Mapbox', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using Mapbox') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from iso3166 import countries + from cartodb_services.tools import ServiceManager, QuotaExceededException + from cartodb_services.tomtom import TomTomGeocoder + from cartodb_services.tools.country import country_to_iso3 + from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD) + + try: + service_manager.assert_within_limits() + geocoder = TomTomGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + + country_iso3166 = None + if country: + country_iso3 = country_to_iso3(country) + if country_iso3: + country_iso3166 = countries.get(country_iso3).alpha2.lower() + + coordinates = geocoder.geocode(searchtext=searchtext, city=city, + state_province=state_province, + country=country_iso3166) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using TomTom', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using TomTom') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocodio_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL) +RETURNS Geometry AS $$ + from iso3166 import countries + from cartodb_services.tools import ServiceManager, QuotaExceededException + from cartodb_services.geocodio import GeocodioGeocoder + from cartodb_services.tools.country import country_to_iso3 + from cartodb_services.refactor.service.geocodio_geocoder_config import GeocodioGeocoderConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('geocoder', GeocodioGeocoderConfigBuilder, username, orgname, GD) + + try: + service_manager.assert_within_limits() + geocoder = GeocodioGeocoder(service_manager.config.geocodio_api_key, service_manager.logger, service_manager.config.service_params) + + country_iso3166 = None + if country: + country_iso3 = country_to_iso3(country) + if country_iso3: + country_iso3166 = countries.get(country_iso3).alpha2.lower() + + coordinates = geocoder.geocode(searchtext=searchtext, city=city, + state_province=state_province, + country=country_iso3166) + if coordinates: + service_manager.quota_service.increment_success_service_use() + plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"]) + point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0] + return point['st_setsrid'] + else: + service_manager.quota_service.increment_empty_service_use() + return None + except QuotaExceededException as qe: + service_manager.quota_service.increment_failed_service_use() + return None + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to geocode street point using Geocodio', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode street point using Geocodio') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_get_rate_limit( + username TEXT, + orgname TEXT, + service TEXT) +RETURNS JSON AS $$ + import json + from cartodb_services.config import ServiceConfiguration, RateLimitsConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_config = ServiceConfiguration(service, username, orgname) + rate_limit_config = RateLimitsConfigBuilder(service_config.server, service_config.user, service_config.org, service=service, username=username, orgname=orgname).get() + if rate_limit_config.is_limited(): + return json.dumps({'limit': rate_limit_config.limit, 'period': rate_limit_config.period}) + else: + return None +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_set_user_rate_limit( + username TEXT, + orgname TEXT, + service TEXT, + rate_limit_json JSON) +RETURNS VOID AS $$ + import json + from cartodb_services.config import RateLimitsConfig, RateLimitsConfigSetter + + import cartodb_services + cartodb_services.init(plpy, GD) + + config_setter = RateLimitsConfigSetter(service=service, username=username, orgname=orgname) + if rate_limit_json: + rate_limit = json.loads(rate_limit_json) + limit = rate_limit.get('limit', None) + period = rate_limit.get('period', None) + else: + limit = None + period = None + config = RateLimitsConfig(service=service, username=username, limit=limit, period=period) + config_setter.set_user_rate_limits(config) +$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_set_org_rate_limit( + username TEXT, + orgname TEXT, + service TEXT, + rate_limit_json JSON) +RETURNS VOID AS $$ + import json + from cartodb_services.config import RateLimitsConfig, RateLimitsConfigSetter + + import cartodb_services + cartodb_services.init(plpy, GD) + + config_setter = RateLimitsConfigSetter(service=service, username=username, orgname=orgname) + if rate_limit_json: + rate_limit = json.loads(rate_limit_json) + limit = rate_limit.get('limit', None) + period = rate_limit.get('period', None) + else: + limit = None + period = None + config = RateLimitsConfig(service=service, username=username, limit=limit, period=period) + config_setter.set_org_rate_limits(config) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_set_server_rate_limit( + username TEXT, + orgname TEXT, + service TEXT, + rate_limit_json JSON) +RETURNS VOID AS $$ + import json + from cartodb_services.config import RateLimitsConfig, RateLimitsConfigSetter + + import cartodb_services + cartodb_services.init(plpy, GD) + + config_setter = RateLimitsConfigSetter(service=service, username=username, orgname=orgname) + if rate_limit_json: + rate_limit = json.loads(rate_limit_json) + limit = rate_limit.get('limit', None) + period = rate_limit.get('period', None) + else: + limit = None + period = None + config = RateLimitsConfig(service=service, username=username, limit=limit, period=period) + config_setter.set_server_rate_limits(config) +$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE; +-- TODO: could cartodb_id be replaced by rowid, maybe needing extra care for offset? +CREATE TYPE cdb_dataservices_server.geocoding AS ( + cartodb_id integer, + the_geom geometry(Point,4326), + metadata jsonb +); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + import json + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + + plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + params = {'username': username, 'orgname': orgname, 'searches': json.loads(searches)} + + with metrics('cdb_bulk_geocode_street_point', user_geocoder_config, logger, params): + if user_geocoder_config.google_geocoder: + provider_function = "_cdb_bulk_google_geocode_street_point"; + elif user_geocoder_config.heremaps_geocoder: + provider_function = "_cdb_bulk_heremaps_geocode_street_point"; + elif user_geocoder_config.tomtom_geocoder: + provider_function = "_cdb_bulk_tomtom_geocode_street_point"; + elif user_geocoder_config.mapbox_geocoder: + provider_function = "_cdb_bulk_mapbox_geocode_street_point"; + elif user_geocoder_config.geocodio_geocoder: + provider_function = "_cdb_bulk_geocodio_geocode_street_point"; + else: + raise Exception('Requested geocoder is not available') + + plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.{}($1, $2, $3); ".format(provider_function), ["text", "text", "jsonb"]) + return plpy.execute(plan, [username, orgname, searches]) + +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_google_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import LegacyServiceManager + from cartodb_services.google import GoogleMapsBulkGeocoder + + service_manager = LegacyServiceManager('geocoder', username, orgname, GD) + geocoder = GoogleMapsBulkGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_heremaps_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import LegacyServiceManager + from cartodb_services.here import HereMapsBulkGeocoder + + service_manager = LegacyServiceManager('geocoder', username, orgname, GD) + geocoder = HereMapsBulkGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_tomtom_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import ServiceManager + from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder + from cartodb_services.tomtom import TomTomBulkGeocoder + from cartodb_services.tools import Logger + import cartodb_services + cartodb_services.init(plpy, GD) + + logger_config = GD["logger_config"] + logger = Logger(logger_config) + service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD) + geocoder = TomTomBulkGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_mapbox_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import ServiceManager + from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder + from cartodb_services.mapbox import MapboxBulkGeocoder + from cartodb_services.tools import Logger + import cartodb_services + cartodb_services.init(plpy, GD) + + logger_config = GD["logger_config"] + logger = Logger(logger_config) + service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD) + geocoder = MapboxBulkGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocodio_geocode_street_point(username TEXT, orgname TEXT, searches jsonb) +RETURNS SETOF cdb_dataservices_server.geocoding AS $$ + from cartodb_services import run_street_point_geocoder + from cartodb_services.tools import ServiceManager + from cartodb_services.refactor.service.geocodio_geocoder_config import GeocodioGeocoderConfigBuilder + from cartodb_services.geocodio import GeocodioBulkGeocoder + from cartodb_services.tools import Logger + import cartodb_services + cartodb_services.init(plpy, GD) + + logger_config = GD["logger_config"] + logger = Logger(logger_config) + service_manager = ServiceManager('geocoder', GeocodioGeocoderConfigBuilder, username, orgname, GD) + geocoder = GeocodioBulkGeocoder(service_manager.config.geocodio_api_key, service_manager.logger, service_manager.config.service_params) + return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches) +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin0_polygon(username text, orgname text, country_name text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'country_name': country_name} + + with metrics('cdb_geocode_admin0_polygon', user_geocoder_config, logger, params): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin0_polygon(trim($1)) AS mypolygon", ["text"]) + rv = plpy.execute(plan, [country_name], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode admin0 polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode admin0 polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_admin0_polygon(country_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT n.the_geom as geom INTO ret + FROM (SELECT q, lower(regexp_replace(q, '[^a-zA-Z\u00C0-\u00ff]+', '', 'g'))::text x + FROM (SELECT country_name q) g) d + LEFT OUTER JOIN admin0_synonyms s ON name_ = d.x + LEFT OUTER JOIN ne_admin0_v3 n ON s.adm0_a3 = n.adm0_a3 GROUP BY d.q, n.the_geom, s.adm0_a3; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; +---- cdb_geocode_admin1_polygon(admin1_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin1_polygon(username text, orgname text, admin1_name text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'admin1_name': admin1_name} + + with metrics('cdb_geocode_admin1_polygon', user_geocoder_config, logger, params): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1)) AS mypolygon", ["text"]) + rv = plpy.execute(plan, [admin1_name], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode admin1 polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode admin1 polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +---- cdb_geocode_admin1_polygon(admin1_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin1_polygon(username text, orgname text, admin1_name text, country_name text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + with metrics('cdb_geocode_admin1_polygon', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1), trim($2)) AS mypolygon", ["text", "text"]) + rv = plpy.execute(plan, [admin1_name, country_name], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode admin1 polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode admin1 polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension + +---- cdb_geocode_admin1_polygon(admin1_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_admin1_polygon(admin1_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT q, ( + SELECT the_geom + FROM global_province_polygons + WHERE d.c = ANY (synonyms) + ORDER BY frequency DESC LIMIT 1 + ) geom + FROM ( + SELECT + trim(replace(lower(admin1_name),'.',' ')) c, admin1_name q + ) d + ) v; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +---- cdb_geocode_admin1_polygon(admin1_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_admin1_polygon(admin1_name text, country_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + WITH p AS (SELECT r.c, r.q, (SELECT iso3 FROM country_decoder WHERE lower(country_name) = ANY (synonyms)) i FROM (SELECT trim(replace(lower(admin1_name),'.',' ')) c, country_name q) r) + SELECT + geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_province_polygons + WHERE p.c = ANY (synonyms) + AND iso3 = p.i + ORDER BY frequency DESC LIMIT 1 + ) geom + FROM p) n; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +---- cdb_geocode_namedplace_point(city_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text) +RETURNS Geometry AS $$ + import spiexceptions + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + try: + street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3) as point;", ["text", "text", "text"]) + return plpy.execute(street_point, [username, orgname, city_name])[0]['point'] + except spiexceptions.ExternalRoutineException as e: + import sys + logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname}) + internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3) as point;", ["text", "text", "text"]) + return plpy.execute(internal_plan, [username, orgname, city_name])[0]['point'] +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +---- cdb_geocode_namedplace_point(city_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, country_name text) +RETURNS Geometry AS $$ + import spiexceptions + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + try: + street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, NULL, $4) as point;", ["text", "text", "text", "text"]) + return plpy.execute(street_point, [username, orgname, city_name, country_name])[0]['point'] + except spiexceptions.ExternalRoutineException as e: + import sys + logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname}) + internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, NULL, $4) as point;", ["text", "text", "text", "text"]) + return plpy.execute(internal_plan, [username, orgname, city_name, country_name])[0]['point'] +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +---- cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, admin1_name text, country_name text) +RETURNS Geometry AS $$ + import spiexceptions + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + try: + street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, $4, $5) as point;", ["text", "text", "text", "text", "text"]) + return plpy.execute(street_point, [username, orgname, city_name, admin1_name, country_name])[0]['point'] + except spiexceptions.ExternalRoutineException as e: + import sys + logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname}) + internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, $4, $5) as point;", ["text", "text", "text", "text", "text"]) + return plpy.execute(internal_plan, [username, orgname, city_name, admin1_name, country_name])[0]['point'] +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_internal_geocode_namedplace(username text, orgname text, city_name text, admin1_name text DEFAULT NULL, country_name text DEFAULT NULL) +RETURNS Geometry AS $$ + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig, metrics + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'city_name': city_name, 'admin1_name': admin1_name, 'country_name': country_name} + + with metrics('cdb_geocode_namedplace_point', user_geocoder_config, logger, params): + try: + if admin1_name and country_name: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2), trim($3)) AS mypoint", ["text", "text", "text"]) + rv = plpy.execute(plan, [city_name, admin1_name, country_name], 1) + elif country_name: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2)) AS mypoint", ["text", "text"]) + rv = plpy.execute(plan, [city_name, country_name], 1) + else: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1)) AS mypoint", ["text"]) + rv = plpy.execute(plan, [city_name], 1) + result = rv[0]["mypoint"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode namedplace point', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode namedplace point') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension + +---- cdb_geocode_namedplace_point(city_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_namedplace_point(city_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + WITH best AS (SELECT s AS q, (SELECT the_geom FROM global_cities_points_limited gp WHERE gp.lowername = lower(p.s) ORDER BY population DESC LIMIT 1) AS geom FROM (SELECT city_name as s) p), + next AS (SELECT p.s AS q, (SELECT gp.the_geom FROM global_cities_points_limited gp, global_cities_alternates_limited ga WHERE lower(p.s) = ga.lowername AND ga.geoname_id = gp.geoname_id ORDER BY preferred DESC LIMIT 1) geom FROM (SELECT city_name as s) p WHERE p.s NOT IN (SELECT q FROM best WHERE geom IS NOT NULL)) + SELECT q, geom, TRUE AS success FROM best WHERE geom IS NOT NULL + UNION ALL + SELECT q, geom, CASE WHEN geom IS NULL THEN FALSE ELSE TRUE END AS success FROM next + ) v; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +---- cdb_geocode_namedplace_point(city_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_namedplace_point(city_name text, country_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + WITH p AS (SELECT r.s, r.c, (SELECT iso2 FROM country_decoder WHERE lower(r.c) = ANY (synonyms)) i FROM (SELECT city_name AS s, country_name::text AS c) r), + best AS (SELECT p.s AS q, p.c AS c, (SELECT gp.the_geom AS geom FROM global_cities_points_limited gp WHERE gp.lowername = lower(p.s) AND gp.iso2 = p.i ORDER BY population DESC LIMIT 1) AS geom FROM p), + next AS (SELECT p.s AS q, p.c AS c, (SELECT gp.the_geom FROM global_cities_points_limited gp, global_cities_alternates_limited ga WHERE lower(p.s) = ga.lowername AND gp.iso2 = p.i AND ga.geoname_id = gp.geoname_id ORDER BY preferred DESC LIMIT 1) geom FROM p WHERE p.s NOT IN (SELECT q FROM best WHERE c = p.c AND geom IS NOT NULL)) + SELECT geom FROM best WHERE geom IS NOT NULL + UNION ALL + SELECT geom FROM next + ) v; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +---- cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + WITH inputcountry AS ( + SELECT iso2 as isoTwo FROM country_decoder WHERE lower(country_name) = ANY (synonyms) LIMIT 1 + ), + p AS ( + SELECT r.s, r.a1, (SELECT admin1 FROM admin1_decoder, inputcountry WHERE lower(r.a1) = ANY (synonyms) AND admin1_decoder.iso2 = inputcountry.isoTwo LIMIT 1) i FROM (SELECT city_name AS s, admin1_name::text AS a1) r), + best AS (SELECT p.s AS q, p.a1 as a1, (SELECT gp.the_geom AS geom FROM global_cities_points_limited gp WHERE gp.lowername = lower(p.s) AND gp.admin1 = p.i ORDER BY population DESC LIMIT 1) AS geom FROM p), + next AS (SELECT p.s AS q, p.a1 AS a1, (SELECT gp.the_geom FROM global_cities_points_limited gp, global_cities_alternates_limited ga WHERE lower(p.s) = ga.lowername AND ga.admin1 = p.i AND ga.geoname_id = gp.geoname_id ORDER BY preferred DESC LIMIT 1) geom FROM p WHERE p.s NOT IN (SELECT q FROM best WHERE geom IS NOT NULL)) + SELECT geom FROM best WHERE geom IS NOT NULL + UNION ALL + SELECT geom FROM next + ) v; + + RETURN ret; + END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'code': code} + + with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger, params): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1)) AS mypoint", ["text"]) + rv = plpy.execute(plan, [code], 1) + result = rv[0]["mypoint"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code point') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code double precision) +RETURNS Geometry AS $$ + SELECT cdb_dataservices_server.cdb_geocode_postalcode_point(username, orgname, code::text); +$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code text, country text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1), trim($2)) AS mypoint", ["TEXT", "TEXT"]) + rv = plpy.execute(plan, [code, country], 1) + result = rv[0]["mypoint"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code point') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code double precision, country text) +RETURNS Geometry AS $$ + SELECT cdb_dataservices_server.cdb_geocode_postalcode_point(username, orgname, code::text, country); +$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1)) AS mypolygon", ["text"]) + rv = plpy.execute(plan, [code], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code double precision) +RETURNS Geometry AS $$ + SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon(username, orgname, code::text) +$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; + + + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code text, country text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1), trim($2)) AS mypolygon", ["TEXT", "TEXT"]) + rv = plpy.execute(plan, [code, country], 1) + result = rv[0]["mypolygon"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code double precision, country text) +RETURNS Geometry AS $$ + SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon(username, orgname, code::text, country); +$$ LANGUAGE SQL STABLE PARALLEL RESTRICTED; + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_point(code text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_postal_code_points + WHERE postal_code = upper(d.q) + LIMIT 1 + ) geom + FROM (SELECT code q) d + ) v; + + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_point(code text, country text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_postal_code_points + WHERE postal_code = upper(d.q) + AND iso3 = ( + SELECT iso3 FROM country_decoder WHERE + lower(country) = ANY (synonyms) LIMIT 1 + ) + LIMIT 1 + ) geom + FROM (SELECT code q) d + ) v; + + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_polygon(code text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_postal_code_polygons + WHERE postal_code = upper(d.q) + LIMIT 1 + ) geom + FROM (SELECT code q) d + ) v; + + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_postalcode_polygon(code text, country text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + BEGIN + SELECT geom INTO ret + FROM ( + SELECT + q, ( + SELECT the_geom + FROM global_postal_code_polygons + WHERE postal_code = upper(d.q) + AND iso3 = ( + SELECT iso3 FROM country_decoder WHERE + lower(country) = ANY (synonyms) LIMIT 1 + ) + LIMIT 1 + ) geom + FROM (SELECT code q) d + ) v; + + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_ipaddress_point(username text, orgname text, ip text) +RETURNS Geometry AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.metrics import QuotaService + from cartodb_services.metrics import InternalGeocoderConfig + from cartodb_services.tools import Logger,LoggerConfig + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_geocoder_config, redis_conn) + + params = {'username': username, 'orgname': orgname, 'ip': ip} + + with metrics('cdb_geocode_ipaddress_point', user_geocoder_config, logger): + try: + plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_ipaddress_point(trim($1)) AS mypoint", ["TEXT"]) + rv = plpy.execute(plan, [ip], 1) + result = rv[0]["mypoint"] + if result: + quota_service.increment_success_service_use() + return result + else: + quota_service.increment_empty_service_use() + return None + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to geocode postal code polygon') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-------------------------------------------------------------------------------- + +-- Implementation of the server extension +-- Note: these functions depend on the cdb_geocoder extension +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_geocode_ipaddress_point(ip text) +RETURNS Geometry AS $$ + DECLARE + ret Geometry; + + new_ip INET; + BEGIN + BEGIN + IF family(ip::inet) = 6 THEN + new_ip := ip::inet; + ELSE + new_ip := ('::ffff:' || ip)::inet; + END IF; + EXCEPTION WHEN OTHERS THEN + SELECT NULL as geom INTO ret; + RETURN ret; + END; + + WITH + ips AS (SELECT ip s, new_ip net), + matches AS (SELECT s, (SELECT the_geom FROM ip_address_locations WHERE network_start_ip <= ips.net ORDER BY network_start_ip DESC LIMIT 1) geom FROM ips) + SELECT geom INTO ret + FROM matches; + RETURN ret; +END +$$ LANGUAGE plpgsql STABLE PARALLEL SAFE; +CREATE TYPE cdb_dataservices_server.isoline AS (center geometry(Geometry,4326), data_range integer, the_geom geometry(Multipolygon,4326)); + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_routing_isolines(username TEXT, orgname TEXT, type TEXT, source geometry(Geometry, 4326), mode TEXT, data_range integer[], options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + import json + from cartodb_services.here import HereMapsRoutingIsoline + from cartodb_services.metrics import QuotaService + from cartodb_services.here.types import geo_polyline_to_multipolygon + from cartodb_services.tools import Logger,LoggerConfig + + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + # -- Check the quota + quota_service = QuotaService(user_isolines_routing_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + try: + client = HereMapsRoutingIsoline(user_isolines_routing_config.heremaps_app_id, + user_isolines_routing_config.heremaps_app_code, logger) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + source_str = 'geo!%f,%f' % (lat, lon) + else: + source_str = None + + if type == 'isodistance': + resp = client.calculate_isodistance(source_str, mode, data_range, options) + elif type == 'isochrone': + resp = client.calculate_isochrone(source_str, mode, data_range, options) + + if resp: + result = [] + for isoline in resp: + data_range_n = isoline['range'] + polyline = isoline['geom'] + multipolygon = geo_polyline_to_multipolygon(polyline) + result.append([source, data_range_n, multipolygon]) + quota_service.increment_success_service_use() + quota_service.increment_isolines_service_use(len(resp)) + return result + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get mapzen isolines') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + import json + from cartodb_services.mapzen import MatrixClient, MapzenIsolines + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + quota_service = QuotaService(user_isolines_routing_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + try: + client = MatrixClient(user_isolines_routing_config.mapzen_matrix_api_key, logger, user_isolines_routing_config.mapzen_matrix_service_params) + mapzen_isolines = MapzenIsolines(client, logger) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = {'lat': lat, 'lon': lon} + else: + raise Exception('source is NULL') + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapzen_isolines.calculate_isodistance(origin, mode, r) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l['lon'], l['lat']) for l in locations]) + sql = "SELECT ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + quota_service.increment_success_service_use() + quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get mapzen isolines') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = mapbox_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.tomtom import TomTomIsolines + from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM + from cartodb_services.tools import Coordinate + from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_TOMTOM.get(mode) + + # -- TODO Support options properly + isolines = {} + for r in data_range: + isoline = tomtom_isolines.calculate_isodistance(origin, r, profile) + isolines[r] = isoline + + result = [] + for r in data_range: + + if len(isolines[r]) >= 3: + # -- TODO encapsulate this block into a func/method + locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point + wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations]) + sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates) + multipolygon = plpy.execute(sql, 1)[0]['geom'] + else: + multipolygon = None + + result.append([source, r, multipolygon]) + + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(isolines)) + return result + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get TomTom isolines', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get TomTom isolines') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + import json + from cartodb_services.mapzen import MatrixClient, MapzenIsochrones + from cartodb_services.metrics import QuotaService + from cartodb_services.tools import Logger,LoggerConfig + from cartodb_services.mapzen.types import coordinates_to_polygon + + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)] + + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + # -- Check the quota + quota_service = QuotaService(user_isolines_routing_config, redis_conn) + if not quota_service.check_user_quota(): + raise Exception('You have reached the limit of your quota') + + try: + mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key, + logger, user_isolines_routing_config.mapzen_isochrones_service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = {'lat': lat, 'lon': lon} + else: + raise Exception('source is NULL') + + resp = mapzen_isochrones.isochrone(origin, mode, data_range) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + quota_service.increment_success_service_use() + quota_service.increment_isolines_service_use(len(result)) + return result + else: + quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + quota_service.increment_failed_service_use() + logger.error('Error trying to get mapzen isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get mapzen isochrones') + finally: + quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.mapbox import MapboxIsolines + from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + mapbox_isolines = MapboxIsolines(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_MAPBOX.get(mode) + + resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get Mapbox isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; + +CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones( + username TEXT, + orgname TEXT, + source geometry(Geometry, 4326), + mode TEXT, + data_range integer[], + options text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.tools import ServiceManager + from cartodb_services.tomtom import TomTomIsolines + from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM + from cartodb_services.tools import Coordinate + from cartodb_services.tools.coordinates import coordinates_to_polygon + from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder + + import cartodb_services + cartodb_services.init(plpy, GD) + + service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD) + service_manager.assert_within_limits() + + try: + tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params) + + if source: + lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat'] + lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon'] + origin = Coordinate(lon,lat) + else: + raise Exception('source is NULL') + + profile = TRANSPORT_MODE_TO_TOMTOM.get(mode) + + resp = tomtom_isolines.calculate_isochrone(origin, data_range, profile) + + if resp: + result = [] + for isochrone in resp: + result_polygon = coordinates_to_polygon(isochrone.coordinates) + if result_polygon: + result.append([source, isochrone.duration, result_polygon]) + else: + result.append([source, isochrone.duration, None]) + service_manager.quota_service.increment_success_service_use() + service_manager.quota_service.increment_isolines_service_use(len(result)) + return result + else: + service_manager.quota_service.increment_empty_service_use() + return [] + except BaseException as e: + import sys + service_manager.quota_service.increment_failed_service_use() + service_manager.logger.error('Error trying to get TomTom isochrones', sys.exc_info(), data={"username": username, "orgname": orgname}) + raise Exception('Error trying to get TomTom isochrones') + finally: + service_manager.quota_service.increment_total_service_use() +$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + if user_isolines_config.google_services_user: + raise Exception('This service is not available for google service users.') + + params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + + with metrics('cdb_isodistance', user_isolines_config, logger, params): + if user_isolines_config.heremaps_provider: + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + else: + raise Exception('Requested isolines provider is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- heremaps isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_here_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + type = 'isodistance' + + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(here_plan, [username, orgname, type, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapzen isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapbox isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- tomtom isodistance +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + from cartodb_services.metrics import metrics + from cartodb_services.tools import Logger + + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + plpy.execute("SELECT cdb_dataservices_server._get_logger_config()") + logger_config = GD["logger_config"] + logger = Logger(logger_config) + + if user_isolines_config.google_services_user: + raise Exception('This service is not available for google service users.') + + params = {'username': username, 'orgname': orgname, 'source': source, 'mode': mode, 'range': range, 'options': options} + + with metrics('cdb_isochrone', user_isolines_config, logger, params): + if user_isolines_config.heremaps_provider: + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(here_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapzen_provider: + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.mapbox_provider: + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + elif user_isolines_config.tomtom_provider: + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + else: + raise Exception('Requested isolines provider is not available') +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- heremaps isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_here_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + type = 'isochrone' + + here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(here_plan, [username, orgname, type, source, mode, range, options]) + + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapzen isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options]) + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- mapbox isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options]) + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; + +-- tomtom isochrone +CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[]) +RETURNS SETOF cdb_dataservices_server.isoline AS $$ + plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username)) + redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection'] + plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname))) + user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)] + + tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"]) + result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options]) + return result +$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED; +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$$; diff --git a/server/extension/cdb_dataservices_server--0.35.1--0.36.0.sql b/server/extension/old_versions/cdb_dataservices_server--0.35.1--0.36.0.sql similarity index 100% rename from server/extension/cdb_dataservices_server--0.35.1--0.36.0.sql rename to server/extension/old_versions/cdb_dataservices_server--0.35.1--0.36.0.sql diff --git a/server/extension/cdb_dataservices_server--0.36.0--0.35.1.sql b/server/extension/old_versions/cdb_dataservices_server--0.36.0--0.35.1.sql similarity index 100% rename from server/extension/cdb_dataservices_server--0.36.0--0.35.1.sql rename to server/extension/old_versions/cdb_dataservices_server--0.36.0--0.35.1.sql diff --git a/server/extension/cdb_dataservices_server--0.36.0.sql b/server/extension/old_versions/cdb_dataservices_server--0.36.0.sql similarity index 100% rename from server/extension/cdb_dataservices_server--0.36.0.sql rename to server/extension/old_versions/cdb_dataservices_server--0.36.0.sql From 6b50d004bdcadaa886675f8aecd53e5d2b212894 Mon Sep 17 00:00:00 2001 From: antoniocarlon Date: Tue, 11 Feb 2020 15:45:04 +0100 Subject: [PATCH 20/20] Fix error --- .../cartodb_services/cartodb_services/metrics/config.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py index 68c9a9c..b762f3b 100644 --- a/server/lib/python/cartodb_services/cartodb_services/metrics/config.py +++ b/server/lib/python/cartodb_services/cartodb_services/metrics/config.py @@ -255,7 +255,7 @@ class IsolinesRoutingConfig(ServiceConfig): self._mapzen_matrix_service_params = db_config.mapzen_matrix_service_params self._mapzen_isochrones_service_params = db_config.mapzen_isochrones_service_params elif self._isolines_provider == self.MAPBOX_PROVIDER: - self._mapbox_matrix_api_key = self._db_config.mapbox_matrix_api_key + self._mapbox_matrix_api_keys = self._db_config.mapbox_matrix_api_keys self._mapbox_matrix_service_params = db_config.mapbox_matrix_service_params self._mapbox_isochrones_service_params = db_config.mapbox_isochrones_service_params elif self._isolines_provider == self.TOMTOM_PROVIDER: @@ -318,8 +318,8 @@ class IsolinesRoutingConfig(ServiceConfig): return self._isolines_provider == self.MAPZEN_PROVIDER @property - def mapbox_matrix_api_key(self): - return self._mapbox_matrix_api_key + def mapbox_matrix_api_keys(self): + return self._mapbox_matrix_api_keys @property def mapbox_matrix_service_params(self): @@ -679,7 +679,7 @@ class ServicesDBConfig: # Note: We are no longer using the Matrix API but we have avoided renaming the `matrix` parameter # to `isolines` to ensure retrocompatibility - self._mapbox_matrix_api_key = mapbox_conf['matrix']['api_key'] + self._mapbox_matrix_api_keys = mapbox_conf['matrix']['api_keys'] self._mapbox_matrix_quota = mapbox_conf['matrix']['monthly_quota'] self._mapbox_matrix_service_params = mapbox_conf['matrix'].get('service', {}) self._mapbox_isochrones_service_params = mapbox_conf.get('isochrones', {}).get('service', {})