+ -- Speed up searches - just use the centroid of the feature
+ -- cheaper but less acurate
+ place_centroid := ST_PointOnSurface(NEW.geometry);
+ NEW.centroid := null;
+ NEW.postcode := null;
+ --DEBUG: RAISE WARNING 'Computing preliminary centroid at %',ST_AsText(place_centroid);
+
+ -- recalculate country and partition
+ IF NEW.rank_search = 4 AND NEW.address is not NULL AND NEW.address ? 'country' THEN
+ -- for countries, believe the mapped country code,
+ -- so that we remain in the right partition if the boundaries
+ -- suddenly expand.
+ NEW.country_code := lower(NEW.address->'country');
+ NEW.partition := get_partition(lower(NEW.country_code));
+ IF NEW.partition = 0 THEN
+ NEW.country_code := lower(get_country_code(place_centroid));
+ NEW.partition := get_partition(NEW.country_code);
+ END IF;
+ ELSE
+ IF NEW.rank_search >= 4 THEN
+ NEW.country_code := lower(get_country_code(place_centroid));
+ ELSE
+ NEW.country_code := NULL;
+ END IF;
+ NEW.partition := get_partition(NEW.country_code);
+ END IF;
+ --DEBUG: RAISE WARNING 'Country updated: "%"', NEW.country_code;
+
+ -- 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_members IN select members from planet_osm_rels r where r.id = NEW.osm_id and r.parts != array[]::bigint[]
+ LOOP
+ FOR i IN 1..array_upper(relation_members, 1) BY 2 LOOP
+ IF relation_members[i+1] in ('', 'main_stream', 'side_stream') AND substring(relation_members[i],1,1) = 'w' THEN
+ --DEBUG: RAISE WARNING 'waterway parent %, child %/%', NEW.osm_id, i, relation_members[i];
+ FOR linked_node_id IN SELECT place_id FROM placex
+ WHERE osm_type = 'W' and osm_id = substring(relation_members[i],2,200)::bigint
+ and class = NEW.class and type in ('river', 'stream', 'canal', 'drain', 'ditch')
+ and ( relation_members[i+1] != 'side_stream' or NEW.name->'name' = name->'name')
+ LOOP
+ UPDATE placex SET linked_place_id = NEW.place_id WHERE place_id = linked_node_id;
+ END LOOP;
+ END IF;
+ END LOOP;
+ END LOOP;
+ --DEBUG: RAISE WARNING 'Waterway processed';
+ END IF;
+
+ -- Adding ourselves to the list simplifies address calculations later
+ INSERT INTO place_addressline (place_id, address_place_id, fromarea, isaddress, distance, cached_rank_address)
+ VALUES (NEW.place_id, NEW.place_id, true, true, 0, NEW.rank_address);
+
+ -- What level are we searching from
+ search_maxrank := NEW.rank_search;
+
+ -- Thought this wasn't needed but when we add new languages to the country_name table
+ -- we need to update the existing names
+ IF NEW.name is not null AND array_upper(akeys(NEW.name),1) > 1 THEN
+ default_language := get_country_language_code(NEW.country_code);
+ IF default_language IS NOT NULL THEN
+ IF NEW.name ? 'name' AND NOT NEW.name ? ('name:'||default_language) THEN
+ NEW.name := NEW.name || hstore(('name:'||default_language), (NEW.name -> 'name'));
+ ELSEIF NEW.name ? ('name:'||default_language) AND NOT NEW.name ? 'name' THEN
+ NEW.name := NEW.name || hstore('name', (NEW.name -> ('name:'||default_language)));
+ END IF;
+ END IF;
+ END IF;
+ --DEBUG: RAISE WARNING 'Local names updated';
+
+ -- Initialise the name vector using our name
+ name_vector := make_keywords(NEW.name);
+ nameaddress_vector := '{}'::int[];
+
+ FOR i IN 1..28 LOOP
+ address_havelevel[i] := false;
+ END LOOP;
+
+ NEW.importance := null;
+ select language||':'||title,importance from get_wikipedia_match(NEW.extratags, NEW.country_code) INTO NEW.wikipedia,NEW.importance;
+ IF NEW.importance IS NULL THEN
+ select language||':'||title,importance from wikipedia_article where osm_type = NEW.osm_type and osm_id = NEW.osm_id order by importance desc limit 1 INTO NEW.wikipedia,NEW.importance;
+ END IF;
+
+--DEBUG: RAISE WARNING 'Importance computed from wikipedia: %', NEW.importance;
+
+ -- ---------------------------------------------------------------------------
+ -- For low level elements we inherit from our parent road
+ IF (NEW.rank_search > 27 OR (NEW.type = 'postcode' AND NEW.rank_search = 25)) THEN
+
+ --DEBUG: RAISE WARNING 'finding street for % %', NEW.osm_type, NEW.osm_id;
+
+ -- We won't get a better centroid, besides these places are too small to care
+ NEW.centroid := place_centroid;
+
+ NEW.parent_place_id := null;
+
+ -- if we have a POI and there is no address information,
+ -- see if we can get it from a surrounding building
+ IF NEW.osm_type = 'N' AND addr_street IS NULL AND addr_place IS NULL
+ AND NEW.housenumber IS NULL THEN
+ FOR location IN select * from placex where ST_Covers(geometry, place_centroid)
+ and address is not null
+ and (address ? 'housenumber' or address ? 'street' or address ? 'place')
+ and rank_search > 28 AND ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon')
+ limit 1
+ LOOP
+ NEW.housenumber := location.address->'housenumber';
+ addr_street := location.address->'street';
+ addr_place := location.address->'place';
+ --DEBUG: RAISE WARNING 'Found surrounding building % %', location.osm_type, location.osm_id;
+ END LOOP;
+ END IF;
+
+ -- We have to find our parent road.
+ -- Copy data from linked items (points on ways, addr:street links, relations)
+
+ -- Is this object part of a relation?
+ FOR relation IN select * from planet_osm_rels where parts @> ARRAY[NEW.osm_id] and members @> ARRAY[lower(NEW.osm_type)||NEW.osm_id]
+ LOOP
+ -- At the moment we only process one type of relation - associatedStreet
+ IF relation.tags @> ARRAY['associatedStreet'] THEN
+ FOR i IN 1..array_upper(relation.members, 1) BY 2 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 and name is not null INTO NEW.parent_place_id;
+ END IF;
+ END LOOP;
+ END IF;
+ END LOOP;
+ --DEBUG: RAISE WARNING 'Checked for street relation (%)', NEW.parent_place_id;
+
+ -- Note that addr:street links can only be indexed once the street itself is indexed
+ IF NEW.parent_place_id IS NULL AND addr_street IS NOT NULL THEN
+ address_street_word_ids := get_name_ids(make_standard_name(addr_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;
+ --DEBUG: RAISE WARNING 'Checked for addr:street (%)', NEW.parent_place_id;
+
+ IF NEW.parent_place_id IS NULL AND addr_place IS NOT NULL THEN
+ address_street_word_ids := get_name_ids(make_standard_name(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;
+ END IF;
+ --DEBUG: RAISE WARNING 'Checked for addr:place (%)', NEW.parent_place_id;
+
+ -- Is this node part of an interpolation?
+ IF NEW.parent_place_id IS NULL AND NEW.osm_type = 'N' THEN
+ FOR location IN
+ SELECT q.parent_place_id FROM location_property_osmline q, planet_osm_ways x
+ WHERE q.linegeo && NEW.geometry and x.id = q.osm_id and NEW.osm_id = any(x.nodes)
+ LIMIT 1
+ LOOP
+ NEW.parent_place_id := location.parent_place_id;
+ END LOOP;
+ END IF;
+ --DEBUG: RAISE WARNING 'Checked for interpolation (%)', NEW.parent_place_id;
+
+ -- Is this node part of a way?
+ IF NEW.parent_place_id IS NULL AND NEW.osm_type = 'N' THEN
+
+ FOR location IN select p.place_id, p.osm_id, p.parent_place_id, p.rank_search, p.address from placex p, planet_osm_ways w
+ where p.osm_type = 'W' and p.rank_search >= 26 and p.geometry && NEW.geometry and w.id = p.osm_id and NEW.osm_id = any(w.nodes)
+ LOOP
+ --DEBUG: RAISE WARNING 'Node is part of way % ', location.osm_id;
+
+ -- Way IS a road then we are on it - that must be our road
+ IF location.rank_search < 28 AND NEW.parent_place_id IS NULL THEN
+--RAISE WARNING 'node in way that is a street %',location;
+ NEW.parent_place_id := location.place_id;
+ END IF;
+ --DEBUG: RAISE WARNING 'Checked if way is street (%)', NEW.parent_place_id;
+
+ -- If the way mentions a street or place address, try that for parenting.
+ IF NEW.parent_place_id IS NULL AND location.address ? 'street' THEN
+ address_street_word_ids := get_name_ids(make_standard_name(location.address->'street'));
+ IF address_street_word_ids IS NOT NULL THEN
+ FOR linkedplacex IN SELECT place_id from getNearestNamedRoadFeature(NEW.partition, place_centroid, address_street_word_ids) LOOP
+ NEW.parent_place_id := linkedplacex.place_id;
+ END LOOP;
+ END IF;
+ END IF;
+ --DEBUG: RAISE WARNING 'Checked for addr:street in way (%)', NEW.parent_place_id;
+
+ IF NEW.parent_place_id IS NULL AND location.address ? 'place' THEN
+ address_street_word_ids := get_name_ids(make_standard_name(location.address->'place'));
+ IF address_street_word_ids IS NOT NULL THEN
+ FOR linkedplacex IN SELECT place_id from getNearestNamedPlaceFeature(NEW.partition, place_centroid, address_street_word_ids) LOOP
+ NEW.parent_place_id := linkedplacex.place_id;
+ END LOOP;
+ END IF;
+ END IF;
+ --DEBUG: RAISE WARNING 'Checked for addr:place in way (%)', NEW.parent_place_id;
+
+ -- Is the WAY part of a relation
+ IF NEW.parent_place_id IS NULL THEN
+ FOR relation IN select * from planet_osm_rels where parts @> ARRAY[location.osm_id] and members @> ARRAY['w'||location.osm_id]
+ LOOP
+ -- At the moment we only process one type of relation - associatedStreet
+ IF relation.tags @> ARRAY['associatedStreet'] AND array_upper(relation.members, 1) IS NOT NULL THEN
+ FOR i IN 1..array_upper(relation.members, 1) BY 2 LOOP
+ 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 and name is not null INTO NEW.parent_place_id;
+ END IF;
+ END LOOP;
+ END IF;
+ END LOOP;
+ END IF;
+ --DEBUG: RAISE WARNING 'Checked for street relation in way (%)', NEW.parent_place_id;