$$
LANGUAGE plpgsql IMMUTABLE;
+CREATE OR REPLACE FUNCTION get_name_ids(lookup_word TEXT)
+ RETURNS INTEGER[]
+ AS $$
+DECLARE
+ lookup_token TEXT;
+ return_word_ids INTEGER[];
+BEGIN
+ lookup_token := ' '||trim(lookup_word);
+ SELECT array_agg(word_id) FROM word WHERE word_token = lookup_token and class is null and type is null into return_word_ids;
+ RETURN return_word_ids;
+END;
+$$
+LANGUAGE plpgsql IMMUTABLE;
+
CREATE OR REPLACE FUNCTION array_merge(a INTEGER[], b INTEGER[])
RETURNS INTEGER[]
AS $$
ELSEIF NEW.class = 'waterway' AND NEW.name is NULL THEN
RETURN NULL;
ELSEIF NEW.class = 'waterway' THEN
- NEW.rank_search := 17;
+ IF NEW.osm_type = 'R' THEN
+ NEW.rank_search := 16;
+ ELSE
+ NEW.rank_search := 17;
+ END IF;
NEW.rank_address := 0;
ELSEIF NEW.class = 'highway' AND NEW.osm_type != 'N' AND NEW.type in ('service','cycleway','path','footway','steps','bridleway','motorway_link','primary_link','trunk_link','secondary_link','tertiary_link') THEN
NEW.rank_search := 27;
search_maxrank INTEGER;
address_maxrank INTEGER;
address_street_word_id INTEGER;
+ address_street_word_ids INTEGER[];
parent_place_id_rank BIGINT;
isin TEXT[];
END IF;
NEW.geometry_sector := geometry_sector(NEW.partition, place_centroid);
+ -- waterway ways are linked when they are part of a relation and have the same class/type
+ IF NEW.osm_type = 'R' and NEW.class = 'waterway' THEN
+ FOR relation IN select * from planet_osm_rels r where r.id = NEW.osm_id
+ LOOP
+ FOR i IN relation.way_off+1..relation.rel_off LOOP
+ IF relation.members[2*i] in ('', 'main_stream') THEN
+ --DEBUG: RAISE WARNING 'waterway parent %, child %/%', NEW.osm_id, i, relation.parts[i];
+ FOR location IN SELECT * FROM placex WHERE osm_type = 'W' and osm_id = relation.parts[i] and class = NEW.class and type = NEW.type
+ LOOP
+ UPDATE placex SET linked_place_id = NEW.place_id WHERE place_id = location.place_id;
+ END LOOP;
+ END IF;
+ END LOOP;
+ END LOOP;
+ END IF;
+
-- Adding ourselves to the list simplifies address calculations later
INSERT INTO place_addressline VALUES (NEW.place_id, NEW.place_id, true, true, 0, NEW.rank_address);
-- Note that addr:street links can only be indexed once the street itself is indexed
IF NEW.parent_place_id IS NULL AND NEW.osm_type = 'N' THEN
+ -- if there is no address information, see if we can get it from a surrounding building
+ IF NEW.street IS NULL AND NEW.addr_place IS NULL AND NEW.housenumber IS NULL THEN
+ FOR location IN select * from placex where ST_Covers(geometry, place_centroid) and rank_search > 28 and (housenumber is not null or street is not null or addr_place is not null) AND ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon')
+ LOOP
+ NEW.housenumber := location.housenumber;
+ NEW.street := location.street;
+ NEW.addr_place := location.addr_place;
+ END LOOP;
+ END IF;
+
-- Is this node part of a relation?
FOR relation IN select * from planet_osm_rels where parts @> ARRAY[NEW.osm_id] and members @> ARRAY['n'||NEW.osm_id]
LOOP
IF NEW.parent_place_id IS NULL AND relation.members[i+1] = 'street' THEN
--RAISE WARNING 'node in relation %',relation;
SELECT place_id from placex where osm_type='W' and osm_id = substring(relation.members[i],2,200)::bigint
- and rank_search = 26 INTO NEW.parent_place_id;
+ and rank_search = 26 and name is not null INTO NEW.parent_place_id;
END IF;
END LOOP;
END IF;
IF NEW.parent_place_id IS NULL AND relation.members[i+1] = 'street' THEN
--RAISE WARNING 'node in way that is in a relation %',relation;
SELECT place_id from placex where osm_type='W' and osm_id = substring(relation.members[i],2,200)::bigint
- and rank_search = 26 INTO NEW.parent_place_id;
+ and rank_search = 26 and name is not null INTO NEW.parent_place_id;
END IF;
END LOOP;
END IF;
END IF;
-- If the way contains an explicit name of a street copy it
- IF NEW.street IS NULL AND NEW.addr_place IS NULL AND location.street IS NOT NULL THEN
+ -- Slightly less strict then above because data is copied from any object.
+ IF NEW.street IS NULL AND NEW.addr_place IS NULL THEN
--RAISE WARNING 'node in way that has a streetname %',location;
NEW.street := location.street;
- END IF;
-
- -- IF the way contains an explicit name of a place copy it
- IF NEW.addr_place IS NULL AND NEW.street IS NULL AND location.addr_place IS NOT NULL THEN
NEW.addr_place := location.addr_place;
END IF;
IF NEW.parent_place_id IS NULL AND relation.members[i+1] = 'street' THEN
--RAISE WARNING 'way that is in a relation %',relation;
SELECT place_id from placex where osm_type='W' and osm_id = substring(relation.members[i],2,200)::bigint
- and rank_search = 26 INTO NEW.parent_place_id;
+ and rank_search = 26 and name is not null INTO NEW.parent_place_id;
END IF;
END LOOP;
END IF;
--RAISE WARNING 'x3 %',NEW.parent_place_id;
IF NEW.parent_place_id IS NULL AND NEW.street IS NOT NULL THEN
- address_street_word_id := get_name_id(make_standard_name(NEW.street));
- IF address_street_word_id IS NOT NULL THEN
- FOR location IN SELECT * from getNearestNamedRoadFeature(NEW.partition, place_centroid, address_street_word_id) LOOP
+ address_street_word_ids := get_name_ids(make_standard_name(NEW.street));
+ IF address_street_word_ids IS NOT NULL THEN
+ FOR location IN SELECT * from getNearestNamedRoadFeature(NEW.partition, place_centroid, address_street_word_ids) LOOP
NEW.parent_place_id := location.place_id;
END LOOP;
END IF;
END IF;
IF NEW.parent_place_id IS NULL AND NEW.addr_place IS NOT NULL THEN
- address_street_word_id := get_name_id(make_standard_name(NEW.addr_place));
- IF address_street_word_id IS NOT NULL THEN
- FOR location IN SELECT * from getNearestNamedPlaceFeature(NEW.partition, place_centroid, address_street_word_id) LOOP
+ address_street_word_ids := get_name_ids(make_standard_name(NEW.addr_place));
+ IF address_street_word_ids IS NOT NULL THEN
+ FOR location IN SELECT * from getNearestNamedPlaceFeature(NEW.partition, place_centroid, address_street_word_ids) LOOP
NEW.parent_place_id := location.place_id;
END LOOP;
END IF;
FOR location IN
select placex.place_id, osm_type, osm_id,
CASE WHEN class = 'place' and type = 'postcode' THEN hstore('name', postcode) ELSE name END as name,
- class, type, admin_level, fromarea, isaddress,
+ CASE WHEN extratags ? 'place' THEN 'place' ELSE class END as class,
+ CASE WHEN extratags ? 'place' THEN extratags->'place' ELSE type END as type,
+ admin_level, fromarea, isaddress,
CASE WHEN address_place_id = for_place_id AND rank_address = 0 THEN 100 WHEN rank_address = 11 THEN 5 ELSE rank_address END as rank_address,
distance,calculated_country_code,postcode
from place_addressline join placex on (address_place_id = placex.place_id)