+ location_isaddress := NOT address_havelevel[location.rank_address];
+ IF location_isaddress AND location.isguess AND location_parent IS NOT NULL THEN
+ location_isaddress := ST_Contains(location_parent,location.centroid);
+ END IF;
+
+ -- RAISE WARNING '% isaddress: %', location.place_id, location_isaddress;
+ -- Add it to the list of search terms
+ IF location.rank_search > 4 THEN
+ nameaddress_vector := array_merge(nameaddress_vector, location.keywords::integer[]);
+ END IF;
+ INSERT INTO place_addressline VALUES (NEW.place_id, location.place_id, true, location_isaddress, location.distance, location.rank_address);
+
+ IF location_isaddress THEN
+
+ address_havelevel[location.rank_address] := true;
+ IF NOT location.isguess THEN
+ SELECT geometry FROM placex WHERE place_id = location.place_id INTO location_parent;
+ END IF;
+
+ IF location.rank_address > parent_place_id_rank THEN
+ NEW.parent_place_id = location.place_id;
+ parent_place_id_rank = location.rank_address;
+ END IF;
+
+ END IF;
+
+--RAISE WARNING ' Terms: (%) %',location, nameaddress_vector;
+
+ END IF;
+
+ END LOOP;
+
+ -- try using the isin value to find parent places
+ IF array_upper(isin_tokens, 1) IS NOT NULL THEN
+ FOR i IN 1..array_upper(isin_tokens, 1) LOOP
+--RAISE WARNING ' getNearestNamedFeature: % % % %',NEW.partition, place_centroid, search_maxrank, isin_tokens[i];
+ IF NOT ARRAY[isin_tokens[i]] <@ nameaddress_vector THEN
+
+ FOR location IN SELECT * from getNearestNamedFeature(NEW.partition, place_centroid, search_maxrank, isin_tokens[i]) LOOP
+
+ --RAISE WARNING ' ISIN: %',location;
+
+ IF location.rank_search > 4 THEN
+ nameaddress_vector := array_merge(nameaddress_vector, location.keywords::integer[]);
+ INSERT INTO place_addressline VALUES (NEW.place_id, location.place_id, false, NOT address_havelevel[location.rank_address], location.distance, location.rank_address);
+ address_havelevel[location.rank_address] := true;
+
+ IF location.rank_address > parent_place_id_rank THEN
+ NEW.parent_place_id = location.place_id;
+ parent_place_id_rank = location.rank_address;
+ END IF;
+ END IF;
+ END LOOP;
+
+ END IF;
+
+ END LOOP;
+ END IF;
+
+ -- for long ways we should add search terms for the entire length
+ IF st_length(NEW.geometry) > 0.05 THEN
+
+ location_rank_search := 0;
+ location_distance := 0;
+
+ FOR location IN SELECT * from getNearFeatures(NEW.partition, NEW.geometry, search_maxrank, isin_tokens) LOOP
+
+ IF location.rank_address != location_rank_search THEN
+ location_rank_search := location.rank_address;
+ location_distance := location.distance * 1.5;
+ END IF;
+
+ IF location.rank_search > 4 AND location.distance < location_distance THEN
+
+ -- Add it to the list of search terms
+ nameaddress_vector := array_merge(nameaddress_vector, location.keywords::integer[]);
+ INSERT INTO place_addressline VALUES (NEW.place_id, location.place_id, true, false, location.distance, location.rank_address);
+
+ END IF;
+
+ END LOOP;
+
+ END IF;
+
+ -- if we have a name add this to the name search table
+ IF NEW.name IS NOT NULL THEN
+
+ IF NEW.rank_search <= 25 THEN
+ result := add_location(NEW.place_id, NEW.calculated_country_code, NEW.partition, name_vector, NEW.rank_search, NEW.rank_address, NEW.geometry);
+ END IF;
+
+ IF NEW.rank_search between 26 and 27 and NEW.class = 'highway' THEN
+ result := insertLocationRoad(NEW.partition, NEW.place_id, NEW.calculated_country_code, NEW.geometry);
+ END IF;
+
+ result := insertSearchName(NEW.partition, NEW.place_id, NEW.calculated_country_code, name_vector, nameaddress_vector, NEW.rank_search, NEW.rank_address, NEW.importance, place_centroid, NEW.geometry);
+
+ END IF;
+
+ -- If we've not managed to pick up a better one - default centroid
+ IF NEW.centroid IS NULL THEN
+ NEW.centroid := place_centroid;
+ END IF;
+
+ END IF;
+
+ RETURN NEW;
+END;
+$$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION placex_delete() RETURNS TRIGGER
+ AS $$
+DECLARE
+ b BOOLEAN;
+ classtable TEXT;
+BEGIN
+ -- RAISE WARNING 'placex_delete % %',OLD.osm_type,OLD.osm_id;
+
+ update placex set linked_place_id = null, indexed_status = 2 where linked_place_id = OLD.place_id and indexed_status = 0;
+ --DEBUG: RAISE WARNING 'placex_delete:01 % %',OLD.osm_type,OLD.osm_id;
+ update placex set linked_place_id = null where linked_place_id = OLD.place_id;
+ --DEBUG: RAISE WARNING 'placex_delete:02 % %',OLD.osm_type,OLD.osm_id;
+
+ IF OLD.rank_address < 30 THEN
+
+ -- mark everything linked to this place for re-indexing
+ --DEBUG: RAISE WARNING 'placex_delete:03 % %',OLD.osm_type,OLD.osm_id;
+ UPDATE placex set indexed_status = 2 from place_addressline where address_place_id = OLD.place_id
+ and placex.place_id = place_addressline.place_id and indexed_status = 0 and place_addressline.isaddress;
+
+ --DEBUG: RAISE WARNING 'placex_delete:04 % %',OLD.osm_type,OLD.osm_id;
+ DELETE FROM place_addressline where address_place_id = OLD.place_id;
+
+ --DEBUG: RAISE WARNING 'placex_delete:05 % %',OLD.osm_type,OLD.osm_id;
+ b := deleteRoad(OLD.partition, OLD.place_id);
+
+ --DEBUG: RAISE WARNING 'placex_delete:06 % %',OLD.osm_type,OLD.osm_id;
+ update placex set indexed_status = 2 where parent_place_id = OLD.place_id and indexed_status = 0;
+ --DEBUG: RAISE WARNING 'placex_delete:07 % %',OLD.osm_type,OLD.osm_id;
+
+ END IF;
+
+ --DEBUG: RAISE WARNING 'placex_delete:08 % %',OLD.osm_type,OLD.osm_id;
+
+ IF OLD.rank_address < 26 THEN
+ b := deleteLocationArea(OLD.partition, OLD.place_id, OLD.rank_search);
+ END IF;
+
+ --DEBUG: RAISE WARNING 'placex_delete:09 % %',OLD.osm_type,OLD.osm_id;
+
+ IF OLD.name is not null THEN
+ b := deleteSearchName(OLD.partition, OLD.place_id);
+ END IF;
+
+ --DEBUG: RAISE WARNING 'placex_delete:10 % %',OLD.osm_type,OLD.osm_id;
+
+ DELETE FROM place_addressline where place_id = OLD.place_id;
+
+ --DEBUG: RAISE WARNING 'placex_delete:11 % %',OLD.osm_type,OLD.osm_id;
+
+ -- remove from tables for special search
+ classtable := 'place_classtype_' || OLD.class || '_' || OLD.type;
+ SELECT count(*)>0 FROM pg_tables WHERE tablename = classtable and schemaname = current_schema() INTO b;
+ IF b THEN
+ EXECUTE 'DELETE FROM ' || classtable::regclass || ' WHERE place_id = $1' USING OLD.place_id;
+ END IF;
+
+ --DEBUG: RAISE WARNING 'placex_delete:12 % %',OLD.osm_type,OLD.osm_id;
+
+ RETURN OLD;
+
+END;
+$$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION place_delete() RETURNS TRIGGER
+ AS $$
+DECLARE
+ has_rank BOOLEAN;
+BEGIN
+
+ --DEBUG: RAISE WARNING 'delete: % % % %',OLD.osm_type,OLD.osm_id,OLD.class,OLD.type;
+
+ -- deleting large polygons can have a massive effect on the system - require manual intervention to let them through
+ IF st_area(OLD.geometry) > 2 and st_isvalid(OLD.geometry) THEN
+ SELECT bool_or(not (rank_address = 0 or rank_address > 26)) as ranked FROM placex WHERE osm_type = OLD.osm_type and osm_id = OLD.osm_id and class = OLD.class and type = OLD.type INTO has_rank;
+ IF has_rank THEN
+ insert into import_polygon_delete values (OLD.osm_type,OLD.osm_id,OLD.class,OLD.type);
+ RETURN NULL;
+ END IF;
+ END IF;
+
+ -- mark for delete
+ UPDATE placex set indexed_status = 100 where osm_type = OLD.osm_type and osm_id = OLD.osm_id and class = OLD.class and type = OLD.type;
+
+ RETURN OLD;
+
+END;