CREATE SERVER osm 
FOREIGN DATA WRAPPER nominatim_fdw 
OPTIONS (url 'https://nominatim.openstreetmap.org');

SET client_min_messages TO debug1;

SELECT nominatim_fdw_version() IS NOT NULL, 
       nominatim_fdw_version() <> '';

\x

SELECT
    osm_id, osm_type, 
	class, 
    type,
	display_name,
	place_id IS NOT NULL AND place_id > 0 AS valid_place_id, 
	place_rank,
    lon, lat, boundingbox, 
	importance, 
	icon, 
	timestamp IS NOT NULL AS valid_timestamp, 
	attribution,
    querystring, 
	polygon AS geom,
	exclude_place_ids, 
	more_url,
    jsonb_pretty(entrances) AS entrances,
    jsonb_pretty(extratags) AS extratags, 
	jsonb_pretty(namedetails) AS namedetails,
    jsonb_pretty(addressdetails) AS addressdetails
FROM nominatim_search(
      server_name => 'osm',
      q => 'einsteinstraße 60, münster, germany',
      extratags => true,
      addressdetails => true,
      namedetails => true,
      polygon => 'polygon_text',
      email => 'jim.jones@uni-muenster.de',
      countrycodes => 'DE,BR,US',
      dedupe => true,
      exclude_place_ids => '42,73',
      viewbox => '7.6036345,51.9659397,7.6039893,51.9661584',
      polygon_threshold => 0.1,
      layer => 'address,poi',
      limit_result => 1,
      bounded => false,
      accept_language => 'de_DE,de,q=0.9',
      entrances => true);


/* unknown address */
SELECT pg_sleep(2);
SELECT *
FROM nominatim_search(
      server_name => 'osm',
      q => 'foo 42, bar');

SELECT pg_sleep(2);
SELECT 
    osm_id, osm_type, 
	class,
    type,
	display_name,
	place_id IS NOT NULL AND place_id > 0 AS valid_place_id, 
	place_rank,
    lon, lat, boundingbox, 
	importance, 
	icon, 
	timestamp IS NOT NULL AS valid_timestamp, 
	attribution,
    querystring, 
	polygon AS geom,
	exclude_place_ids, 
	more_url,
    jsonb_pretty(entrances) AS entrances, 
    jsonb_pretty(extratags) AS extratags, 
	jsonb_pretty(namedetails) AS namedetails,
    jsonb_pretty(addressdetails) AS addressdetails
FROM nominatim_search(
      server_name => 'osm',
      amenity => 'cit',
      polygon => 'polygon_text',
      street => 'einsteinstraße 60',
      city => 'münster',
      state => 'nordrhein westfalen',
      country => 'germany',
      postalcode => '48149',
      email => 'jim.jones@uni-muenster.de',
      countrycodes => 'DE,BR,US',
      featuretype => 'office',
      dedupe => true,
      exclude_place_ids => '42, 73',
      viewbox => '7.6036345,51.9659397,7.6039893,51.9661584',
      polygon_threshold => 0.1,
      layer => 'address',
      limit_result => 1,
      accept_language => 'de_DE,de,q=0.9');

/* q combined with structured params => should error */
SELECT * FROM nominatim_search(server_name => 'osm', q => 'foo', city => 'münster');

/* nothing to search for - should error */
SELECT * FROM nominatim_search(server_name => 'osm');

/* invalid polygon type - raise warning */
SELECT osm_id, osm_type, display_name
FROM nominatim_search(
        server_name => 'osm', 
        q => 'einsteinstraße 60, münster, germany', 
        polygon => 'polygon_foo',
        limit_result => 1);

/* invalid layer */
RESET client_min_messages;
SELECT * FROM nominatim_search(server_name => 'osm', q => 'x', layer => 'address,bogus');
SET client_min_messages TO debug1;

/* nonexistent server */
SELECT * FROM nominatim_reverse(server_name => 'does_not_exist', lon => 0, lat => 0);

SELECT pg_sleep(2);
SELECT count(*) <= 3 AS respects_limit
FROM nominatim_search(server_name => 'osm', q => 'münster', limit_result => 3);

/* nominatim reverse */
SELECT pg_sleep(2);
SELECT 
    osm_id, 
	osm_type, 
	display_name,
	place_id IS NOT NULL AND place_id > 0 AS valid_place_id, 
	place_rank, 
	lon, 
	boundingbox, 
    icon, 
	timestamp IS NOT NULL AS valid_timestamp, 
	attribution,  
	querystring, 
    polygon AS geom,
    jsonb_pretty(entrances) AS entrances, 
	jsonb_pretty(extratags) AS extratags, 
    jsonb_pretty(namedetails) AS namedetails, 
	jsonb_pretty(addressdetails) AS addressdetails
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,        
        polygon => 'polygon_text',
        extratags => true,
        addressdetails => true,
        namedetails => true,
        accept_language => 'de_DE,de,q=0.9',
        email => 'jim.jones@uni-muenster.de',
        polygon_threshold => 0.1,
        zoom => 18,
        entrances => true);

SELECT pg_sleep(2);
SELECT 
    osm_id, 
	osm_type, 
	display_name,
	place_id IS NOT NULL AND place_id > 0 AS valid_place_id, 
	place_rank, 
	lon, 
	boundingbox, 
    icon, 
	timestamp IS NOT NULL AS valid_timestamp, 
	attribution,  
	querystring, 
    polygon AS geom,
    jsonb_pretty(entrances) AS entrances, 
	jsonb_pretty(extratags) AS extratags, 
    jsonb_pretty(namedetails) AS namedetails, 
	jsonb_pretty(addressdetails) AS addressdetails
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,        
        polygon => 'polygon_kml',
        zoom => 18);

SELECT pg_sleep(2);

/* zoom = 8 (county) */
SELECT osm_id, osm_type, display_name
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,        
        polygon => 'polygon_svg',
        zoom => 8);

/* zoom = -1 (disabled) */
SELECT osm_id, osm_type, display_name
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,        
        polygon => 'polygon_svg',
        zoom => -1);

/* invalid zoom level */
SELECT pg_sleep(2);
SELECT osm_id, osm_type, display_name
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,        
        polygon => 'polygon_kml',
        zoom => 19);
SELECT pg_sleep(2);
SELECT osm_id, osm_type, display_name
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,        
        polygon => 'polygon_kml',
        zoom => -2);

/* invalid polygon format */
SELECT pg_sleep(2);
SELECT osm_id, osm_type, display_name
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,
        polygon => 'pOlygON_TexT');
SELECT pg_sleep(2);
SELECT osm_id, osm_type, display_name
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,
        polygon => 'foo');

SELECT pg_sleep(2);
SELECT 
    osm_id, 
	osm_type, 
	display_name,
	place_id IS NOT NULL AND place_id > 0 AS valid_place_id, 
	place_rank, 
	lon, 
	boundingbox, 
    icon, 
	timestamp IS NOT NULL AS valid_timestamp, 
	attribution,  
	querystring, 
    polygon AS geom,
    jsonb_pretty(entrances) AS entrances, 
	jsonb_pretty(extratags) AS extratags, 
    jsonb_pretty(namedetails) AS namedetails, 
	jsonb_pretty(addressdetails) AS addressdetails
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,        
        polygon => 'polygon_svg',
        zoom => 18);

SELECT pg_sleep(2);
SELECT 
    osm_id, 
	osm_type, 
	display_name,
	place_id IS NOT NULL AND place_id > 0 AS valid_place_id, 
	place_rank, 
	lon, 
	boundingbox, 
    icon, 
	timestamp IS NOT NULL AS valid_timestamp, 
	attribution,  
	querystring, 
    polygon AS geom,
    jsonb_pretty(entrances) AS entrances, 
	jsonb_pretty(extratags) AS extratags, 
    jsonb_pretty(namedetails) AS namedetails, 
	jsonb_pretty(addressdetails) AS addressdetails
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 7.6038115,
        lat => 51.9660873,        
        polygon => 'polygon_geojson',
        zoom => 18);

/* invalid coordinates */
SELECT pg_sleep(2);
SELECT osm_id, display_name, boundingbox
FROM nominatim_reverse(
        server_name => 'osm', 
        lon => 4200.37,
        lat => 9999.99,
        extratags => true);

/* longitude out of range */
SELECT pg_sleep(2);
SELECT *
FROM nominatim_reverse(
        server_name => 'osm',
        lon => 200,
        lat => 50);

/* boundary values must be ACCEPTED (inclusive endpoints) */
SELECT pg_sleep(2);
SELECT osm_id IS NOT NULL
FROM nominatim_reverse(
    server_name => 'osm',
    lon => 180,
    lat => 90);

SELECT pg_sleep(2);
SELECT osm_id IS NOT NULL
FROM nominatim_reverse(
        server_name => 'osm',
        lon => -180,
        lat => -90);

/* valid coordinates but no location */
SELECT pg_sleep(2);
SELECT osm_id, display_name
FROM nominatim_reverse(
        server_name => 'osm', lon => 0, lat => -60);

SELECT pg_sleep(2);
SELECT osm_id, display_name
FROM nominatim_reverse(
        server_name => 'osm', lon => 0, lat => 0);

SELECT pg_sleep(2);
SELECT count(*) 
FROM nominatim_lookup(
        server_name => 'osm',
        osm_ids => 'W88291927,R62591');

/* nominatim lookup */
SELECT pg_sleep(2);
SELECT 
    osm_id, osm_type, 
	class,
    type,
	display_name,
	place_id IS NOT NULL AND place_id > 0 AS valid_place_id, 
	place_rank,
    lon, lat, boundingbox, 
	importance, 
	icon, 
	timestamp IS NOT NULL AS valid_timestamp, 
	attribution,
    querystring, 
	polygon AS geom, 
    jsonb_pretty(entrances) AS entrances,
    jsonb_pretty(extratags) AS extratags, 
	jsonb_pretty(namedetails) AS namedetails,
    jsonb_pretty(addressdetails) AS addressdetails
FROM nominatim_lookup(
      server_name => 'osm',
      osm_ids => 'W88291927',
      extratags => true,
      addressdetails => true,
      namedetails => true,
      entrances => true,
      polygon => 'polygon_text',
      email => 'jim.jones@uni-muenster.de',
      polygon_threshold => 0.1,
      accept_language => 'de_DE,de,q=0.9');

/* mix of valid and invalid osm_ids */
SELECT pg_sleep(2);
SELECT osm_id, osm_type, class, type, display_name
FROM nominatim_lookup(
      server_name => 'osm',
      osm_ids => 'W88291927,X99999,F00');

/* invalid osm_ids */
SELECT pg_sleep(2);
SELECT osm_id, osm_type, class, type, display_name
FROM nominatim_lookup(
      server_name => 'osm',
      osm_ids => 'X99999,F00');

/* must error, since osm_ids is required */
SELECT * FROM nominatim_lookup(server_name => 'osm', osm_ids => '');

/* returns 0 rows (STRICT function) */
SELECT * FROM nominatim_lookup(server_name => 'osm', osm_ids => NULL);