X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/6189e0c79b8bbb2ed964b54b79de2b23d289f166..61535c9972e307350c1b91dcb776e210f37d258e:/sql/functions/placex_triggers.sql diff --git a/sql/functions/placex_triggers.sql b/sql/functions/placex_triggers.sql index 3450c1f1..ab8f951f 100644 --- a/sql/functions/placex_triggers.sql +++ b/sql/functions/placex_triggers.sql @@ -1,45 +1,5 @@ -- Trigger functions for the placex table. -CREATE OR REPLACE FUNCTION get_rel_node_members(members TEXT[], memberLabels TEXT[]) - RETURNS SETOF BIGINT - AS $$ -DECLARE - i INTEGER; -BEGIN - FOR i IN 1..ARRAY_UPPER(members,1) BY 2 LOOP - IF members[i+1] = ANY(memberLabels) - AND upper(substring(members[i], 1, 1))::char(1) = 'N' - THEN - RETURN NEXT substring(members[i], 2)::bigint; - END IF; - END LOOP; - - RETURN; -END; -$$ -LANGUAGE plpgsql IMMUTABLE; - --- copy 'name' to or from the default language (if there is a default language) -CREATE OR REPLACE FUNCTION add_default_place_name(country_code VARCHAR(2), - INOUT name HSTORE) - AS $$ -DECLARE - default_language VARCHAR(10); -BEGIN - IF name is not null AND array_upper(akeys(name),1) > 1 THEN - default_language := get_country_language_code(country_code); - IF default_language IS NOT NULL THEN - IF name ? 'name' AND NOT name ? ('name:'||default_language) THEN - name := name || hstore(('name:'||default_language), (name -> 'name')); - ELSEIF name ? ('name:'||default_language) AND NOT name ? 'name' THEN - name := name || hstore('name', (name -> ('name:'||default_language))); - END IF; - END IF; - END IF; -END; -$$ -LANGUAGE plpgsql IMMUTABLE; - -- Find the parent road of a POI. -- -- \returns Place ID of parent object or NULL if none @@ -135,8 +95,7 @@ BEGIN IF fallback THEN IF ST_Area(bbox) < 0.01 THEN -- for smaller features get the nearest road - SELECT place_id FROM getNearestRoadFeature(poi_partition, bbox) - INTO parent_place_id; + SELECT getNearestRoadPlaceId(poi_partition, bbox) INTO parent_place_id; --DEBUG: RAISE WARNING 'Checked for nearest way (%)', parent_place_id; ELSE -- for larger features simply find the area with the largest rank that @@ -205,44 +164,50 @@ BEGIN END IF; END IF; - -- Search for relation members with role admin_center. - IF bnd.osm_type = 'R' and bnd_name is not null - and relation_members is not null THEN - FOR rel_member IN - SELECT get_rel_node_members(relation_members, - ARRAY['admin_center','admin_centre']) as member + -- If extratags has a place tag, look for linked nodes by their place type. + -- Area and node still have to have the same name. + IF bnd.extratags ? 'place' and bnd_name is not null THEN + FOR linked_placex IN + SELECT * FROM placex + WHERE make_standard_name(name->'name') = bnd_name + AND placex.class = 'place' AND placex.type = bnd.extratags->'place' + AND placex.osm_type = 'N' + AND placex.rank_search < 26 -- needed to select the right index + AND _st_covers(bnd.geometry, placex.geometry) LOOP - --DEBUG: RAISE WARNING 'Found admin_center member %', rel_member.member; - FOR linked_placex IN - SELECT * from placex - WHERE osm_type = 'N' and osm_id = rel_member.member - and class = 'place' - LOOP - -- For an admin centre we also want a name match - still not perfect, - -- for example 'new york, new york' - -- But that can be fixed by explicitly setting the label in the data - IF bnd_name = make_standard_name(linked_placex.name->'name') - AND bnd.rank_address = linked_placex.rank_address - THEN - RETURN linked_placex; - END IF; - --DEBUG: RAISE WARNING 'Linked admin_center'; - END LOOP; + --DEBUG: RAISE WARNING 'Found type-matching place node %', linked_placex.osm_id; + RETURN linked_placex; + END LOOP; + END IF; + + IF bnd.extratags ? 'wikidata' THEN + FOR linked_placex IN + SELECT * FROM placex + WHERE placex.class = 'place' AND placex.osm_type = 'N' + AND placex.extratags ? 'wikidata' -- needed to select right index + AND placex.extratags->'wikidata' = bnd.extratags->'wikidata' + AND placex.rank_search < 26 + AND _st_covers(bnd.geometry, placex.geometry) + ORDER BY make_standard_name(name->'name') = bnd_name desc + LOOP + --DEBUG: RAISE WARNING 'Found wikidata-matching place node %', linked_placex.osm_id; + RETURN linked_placex; END LOOP; END IF; -- Name searches can be done for ways as well as relations - IF bnd.osm_type in ('W','R') and bnd_name is not null THEN + IF bnd_name is not null THEN --DEBUG: RAISE WARNING 'Looking for nodes with matching names'; FOR linked_placex IN SELECT placex.* from placex WHERE make_standard_name(name->'name') = bnd_name - AND placex.rank_address = bnd.rank_address + AND ((bnd.rank_address > 0 and placex.rank_address = bnd.rank_address) + OR (bnd.rank_address = 0 and placex.rank_search = bnd.rank_search)) AND placex.osm_type = 'N' AND placex.rank_search < 26 -- needed to select the right index AND _st_covers(bnd.geometry, placex.geometry) LOOP - --DEBUG: RAISE WARNING 'Found matching place node %', linkedPlacex.osm_id; + --DEBUG: RAISE WARNING 'Found matching place node %', linked_placex.osm_id; RETURN linked_placex; END LOOP; END IF; @@ -252,18 +217,181 @@ END; $$ LANGUAGE plpgsql STABLE; + +-- Insert address of a place into the place_addressline table. +-- +-- \param obj_place_id Place_id of the place to compute the address for. +-- \param partition Partition number where the place is in. +-- \param maxrank Rank of the place. All address features must have +-- a search rank lower than the given rank. +-- \param address Address terms for the place. +-- \param geoemtry Geometry to which the address objects should be close. +-- +-- \retval parent_place_id Place_id of the address object that is the direct +-- ancestor. +-- \retval postcode Postcode computed from the address. This is the +-- addr:postcode of one of the address objects. If +-- more than one of has a postcode, the highest ranking +-- one is used. May be NULL. +-- \retval nameaddress_vector Search terms for the address. This is the sum +-- of name terms of all address objects. +CREATE OR REPLACE FUNCTION insert_addresslines(obj_place_id BIGINT, + partition SMALLINT, + maxrank SMALLINT, + address HSTORE, + geometry GEOMETRY, + OUT parent_place_id BIGINT, + OUT postcode TEXT, + OUT nameaddress_vector INT[]) + AS $$ +DECLARE + current_rank_address INTEGER := 0; + location_distance FLOAT := 0; + location_parent GEOMETRY := NULL; + parent_place_id_rank SMALLINT := 0; + + location_isaddress BOOLEAN; + + address_havelevel BOOLEAN[]; + location_keywords INT[]; + + location RECORD; + addr_item RECORD; + + isin_tokens INT[]; + isin TEXT[]; +BEGIN + parent_place_id := 0; + nameaddress_vector := '{}'::int[]; + isin_tokens := '{}'::int[]; + + ---- convert address store to array of tokenids + IF address IS NOT NULL THEN + FOR addr_item IN SELECT * FROM each(address) + LOOP + IF addr_item.key IN ('city', 'tiger:county', 'state', 'suburb', 'province', + 'district', 'region', 'county', 'municipality', + 'hamlet', 'village', 'subdistrict', 'town', + 'neighbourhood', 'quarter', 'parish') + THEN + isin_tokens := array_merge(isin_tokens, + word_ids_from_name(addr_item.value)); + IF NOT %REVERSE-ONLY% THEN + nameaddress_vector := array_merge(nameaddress_vector, + addr_ids_from_name(addr_item.value)); + END IF; + END IF; + END LOOP; + + IF address ? 'is_in' THEN + -- is_in items need splitting + isin := regexp_split_to_array(address->'is_in', E'[;,]'); + IF array_upper(isin, 1) IS NOT NULL THEN + FOR i IN 1..array_upper(isin, 1) LOOP + isin_tokens := array_merge(isin_tokens, + word_ids_from_name(isin[i])); + + -- merge word into address vector + IF NOT %REVERSE-ONLY% THEN + nameaddress_vector := array_merge(nameaddress_vector, + addr_ids_from_name(isin[i])); + END IF; + END LOOP; + END IF; + END IF; + END IF; + IF NOT %REVERSE-ONLY% THEN + nameaddress_vector := array_merge(nameaddress_vector, isin_tokens); + END IF; + + ---- now compute the address terms + FOR i IN 1..28 LOOP + address_havelevel[i] := false; + END LOOP; + + FOR location IN + SELECT * FROM getNearFeatures(partition, geometry, maxrank, isin_tokens) + LOOP + IF location.rank_address != current_rank_address THEN + current_rank_address := location.rank_address; + IF location.isguess THEN + location_distance := location.distance * 1.5; + ELSE + IF location.rank_address <= 12 THEN + -- for county and above, if we have an area consider that exact + -- (It would be nice to relax the constraint for places close to + -- the boundary but we'd need the exact geometry for that. Too + -- expensive.) + location_distance = 0; + ELSE + -- Below county level remain slightly fuzzy. + location_distance := location.distance * 0.5; + END IF; + END IF; + ELSE + CONTINUE WHEN location.keywords <@ location_keywords; + END IF; + + IF location.distance < location_distance OR NOT location.isguess THEN + location_keywords := location.keywords; + + location_isaddress := NOT address_havelevel[location.rank_address]; + --DEBUG: RAISE WARNING 'should be address: %, is guess: %, rank: %', location_isaddress, location.isguess, 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; + + --DEBUG: RAISE WARNING '% isaddress: %', location.place_id, location_isaddress; + -- Add it to the list of search terms + IF NOT %REVERSE-ONLY% THEN + nameaddress_vector := array_merge(nameaddress_vector, + location.keywords::integer[]); + END IF; + + INSERT INTO place_addressline (place_id, address_place_id, fromarea, + isaddress, distance, cached_rank_address) + VALUES (obj_place_id, location.place_id, true, + location_isaddress, location.distance, location.rank_address); + + IF location_isaddress THEN + -- add postcode if we have one + -- (If multiple postcodes are available, we end up with the highest ranking one.) + IF location.postcode is not null THEN + postcode = location.postcode; + END IF; + + address_havelevel[location.rank_address] := true; + -- add a hack against postcode ranks + IF NOT location.isguess + AND location.rank_address != 11 AND location.rank_address != 5 + THEN + SELECT p.geometry FROM placex p + WHERE p.place_id = location.place_id INTO location_parent; + END IF; + + IF location.rank_address > parent_place_id_rank THEN + parent_place_id = location.place_id; + parent_place_id_rank = location.rank_address; + END IF; + END IF; + END IF; + + END LOOP; +END; +$$ +LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION placex_insert() RETURNS TRIGGER AS $$ DECLARE - i INTEGER; postcode TEXT; result BOOLEAN; is_area BOOLEAN; country_code VARCHAR(2); diameter FLOAT; classtable TEXT; - classtype TEXT; BEGIN --DEBUG: RAISE WARNING '% % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type; @@ -281,8 +409,8 @@ BEGIN is_area := ST_GeometryType(NEW.geometry) IN ('ST_Polygon','ST_MultiPolygon'); IF NEW.class in ('place','boundary') - AND NEW.type in ('postcode','postal_code') THEN - + AND NEW.type in ('postcode','postal_code') + THEN IF NEW.address IS NULL OR NOT NEW.address ? 'postcode' THEN -- most likely just a part of a multipolygon postcode boundary, throw it away RETURN NULL; @@ -290,63 +418,28 @@ BEGIN NEW.name := hstore('ref', NEW.address->'postcode'); - SELECT * FROM get_postcode_rank(NEW.country_code, NEW.address->'postcode') - INTO NEW.rank_search, NEW.rank_address; - - IF NOT is_area THEN - NEW.rank_address := 0; - END IF; ELSEIF NEW.class = 'boundary' AND NOT is_area THEN - return NULL; + RETURN NULL; ELSEIF NEW.class = 'boundary' AND NEW.type = 'administrative' - AND NEW.admin_level <= 4 AND NEW.osm_type = 'W' THEN - return NULL; - ELSEIF NEW.osm_type = 'N' AND NEW.class = 'highway' THEN - NEW.rank_search = 30; - NEW.rank_address = 0; - ELSEIF NEW.class = 'landuse' AND NOT is_area THEN - NEW.rank_search = 30; - NEW.rank_address = 0; - ELSE - -- do table lookup stuff - IF NEW.class = 'boundary' and NEW.type = 'administrative' THEN - classtype = NEW.type || NEW.admin_level::TEXT; - ELSE - classtype = NEW.type; - END IF; - SELECT l.rank_search, l.rank_address FROM address_levels l - WHERE (l.country_code = NEW.country_code or l.country_code is NULL) - AND l.class = NEW.class AND (l.type = classtype or l.type is NULL) - ORDER BY l.country_code, l.class, l.type LIMIT 1 - INTO NEW.rank_search, NEW.rank_address; - - IF NEW.rank_search is NULL THEN - NEW.rank_search := 30; - END IF; - - IF NEW.rank_address is NULL THEN - NEW.rank_address := 30; - END IF; + AND NEW.admin_level <= 4 AND NEW.osm_type = 'W' + THEN + RETURN NULL; END IF; - -- some postcorrections - IF NEW.class = 'waterway' AND NEW.osm_type = 'R' THEN - -- Slightly promote waterway relations so that they are processed - -- before their members. - NEW.rank_search := NEW.rank_search - 1; - END IF; + SELECT * INTO NEW.rank_search, NEW.rank_address + FROM compute_place_rank(NEW.country_code, + CASE WHEN is_area THEN 'A' ELSE NEW.osm_type END, + NEW.class, NEW.type, NEW.admin_level, + (NEW.extratags->'capital') = 'yes', + NEW.address->'postcode'); - IF (NEW.extratags -> 'capital') = 'yes' THEN - NEW.rank_search := NEW.rank_search - 1; + -- a country code make no sense below rank 4 (country) + IF NEW.rank_search < 4 THEN + NEW.country_code := NULL; END IF; END IF; - -- a country code make no sense below rank 4 (country) - IF NEW.rank_search < 4 THEN - NEW.country_code := NULL; - END IF; - --DEBUG: RAISE WARNING 'placex_insert:END: % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type; RETURN NEW; -- %DIFFUPDATES% The following is not needed until doing diff updates, and slows the main index process down @@ -369,25 +462,7 @@ BEGIN END IF; ELSE -- mark nearby items for re-indexing, where 'nearby' depends on the features rank_search and is a complete guess :( - diameter := 0; - -- 16 = city, anything higher than city is effectively ignored (polygon required!) - IF NEW.type='postcode' THEN - diameter := 0.05; - ELSEIF NEW.rank_search < 16 THEN - diameter := 0; - ELSEIF NEW.rank_search < 18 THEN - diameter := 0.1; - ELSEIF NEW.rank_search < 20 THEN - diameter := 0.05; - ELSEIF NEW.rank_search = 21 THEN - diameter := 0.001; - ELSEIF NEW.rank_search < 24 THEN - diameter := 0.02; - ELSEIF NEW.rank_search < 26 THEN - diameter := 0.002; -- 100 to 200 meters - ELSEIF NEW.rank_search < 28 THEN - diameter := 0.001; -- 50 to 100 meters - END IF; + diameter := update_place_diameter(NEW.rank_search); IF diameter > 0 THEN -- RAISE WARNING 'placex point insert: % % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type,diameter; IF NEW.rank_search >= 26 THEN @@ -428,33 +503,15 @@ CREATE OR REPLACE FUNCTION placex_update() RETURNS TRIGGER AS $$ DECLARE - search_maxdistance FLOAT[]; - search_mindistance FLOAT[]; - address_havelevel BOOLEAN[]; - i INTEGER; location RECORD; relation_members TEXT[]; - addr_item RECORD; - search_diameter FLOAT; - search_prevdiameter FLOAT; - search_maxrank INTEGER; - address_maxrank INTEGER; - address_street_word_ids INTEGER[]; - parent_place_id_rank BIGINT; + + centroid GEOMETRY; addr_street TEXT; addr_place TEXT; - isin TEXT[]; - isin_tokens INT[]; - - location_rank_search INTEGER; - location_distance FLOAT; - location_parent GEOMETRY; - location_isaddress BOOLEAN; - location_keywords INTEGER[]; - name_vector INTEGER[]; nameaddress_vector INTEGER[]; @@ -495,6 +552,17 @@ BEGIN RETURN NEW; END IF; + -- recompute the ranks, they might change when linking changes + SELECT * INTO NEW.rank_search, NEW.rank_address + FROM compute_place_rank(NEW.country_code, + CASE WHEN ST_GeometryType(NEW.geometry) + IN ('ST_Polygon','ST_MultiPolygon') + THEN 'A' ELSE NEW.osm_type END, + NEW.class, NEW.type, NEW.admin_level, + (NEW.extratags->'capital') = 'yes', + NEW.address->'postcode'); + + --DEBUG: RAISE WARNING 'Copy over address tags'; -- housenumber is a computed field, so start with an empty value NEW.housenumber := NULL; @@ -526,10 +594,10 @@ BEGIN -- Speed up searches - just use the centroid of the feature -- cheaper but less acurate NEW.centroid := ST_PointOnSurface(NEW.geometry); - -- For searching near features rather use the centroid - NEW.postcode := null; --DEBUG: RAISE WARNING 'Computing preliminary centroid at %',ST_AsText(NEW.centroid); + NEW.postcode := null; + -- 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, @@ -564,6 +632,9 @@ BEGIN 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; + IF NOT %REVERSE-ONLY% THEN + DELETE FROM search_name WHERE place_id = linked_node_id; + END IF; END LOOP; END IF; END LOOP; @@ -678,11 +749,19 @@ BEGIN --DEBUG: RAISE WARNING 'Using full index mode for % %', NEW.osm_type, NEW.osm_id; SELECT * INTO location FROM find_linked_place(NEW); IF location.place_id is not null THEN - --DEBUG: RAISE WARNING 'Linked %', location; + --DEBUG: RAISE WARNING 'Linked %', location; + + -- Use the linked point as the centre point of the geometry, + -- but only if it is within the area of the boundary. + centroid := coalesce(location.centroid, ST_Centroid(location.geometry)); + IF centroid is not NULL AND ST_Within(centroid, NEW.geometry) THEN + NEW.centroid := centroid; + END IF; - -- Use this as the centre point of the geometry - NEW.centroid := coalesce(location.centroid, - ST_Centroid(location.geometry)); + -- Use the address rank of the linked place, if it has one + IF location.rank_address between 5 and 25 THEN + NEW.rank_address := location.rank_address; + END IF; -- merge in the label name IF NOT location.name IS NULL THEN @@ -690,13 +769,17 @@ BEGIN END IF; -- merge in extra tags - NEW.extratags := hstore(location.class, location.type) + NEW.extratags := hstore('linked_' || location.class, location.type) || coalesce(location.extratags, ''::hstore) || coalesce(NEW.extratags, ''::hstore); -- mark the linked place (excludes from search results) UPDATE placex set linked_place_id = NEW.place_id WHERE place_id = location.place_id; + -- ensure that those places are not found anymore + IF NOT %REVERSE-ONLY% THEN + DELETE FROM search_name WHERE place_id = location.place_id; + END IF; SELECT wikipedia, importance FROM compute_importance(location.extratags, NEW.country_code, @@ -711,13 +794,9 @@ BEGIN END IF; END IF; - -- What level are we searching from - search_maxrank := NEW.rank_search; - -- Initialise the name vector using our name NEW.name := add_default_place_name(NEW.country_code, NEW.name); name_vector := make_keywords(NEW.name); - nameaddress_vector := '{}'::int[]; -- make sure all names are in the word table IF NEW.admin_level = 2 @@ -728,142 +807,14 @@ BEGIN --DEBUG: RAISE WARNING 'Country names updated'; END IF; - FOR i IN 1..28 LOOP - address_havelevel[i] := false; - END LOOP; - - NEW.parent_place_id = 0; - parent_place_id_rank = 0; - - - -- convert address store to array of tokenids - --DEBUG: RAISE WARNING 'Starting address search'; - isin_tokens := '{}'::int[]; - IF NEW.address IS NOT NULL THEN - FOR addr_item IN SELECT * FROM each(NEW.address) - LOOP - IF addr_item.key IN ('city', 'tiger:county', 'state', 'suburb', 'province', - 'district', 'region', 'county', 'municipality', - 'hamlet', 'village', 'subdistrict', 'town', - 'neighbourhood', 'quarter', 'parish') - THEN - address_street_word_ids := word_ids_from_name(addr_item.value); - IF address_street_word_ids is not null THEN - isin_tokens := array_merge(isin_tokens, address_street_word_ids); - END IF; - IF NOT %REVERSE-ONLY% THEN - address_street_word_ids := addr_ids_from_name(addr_item.value); - IF address_street_word_ids is not null THEN - nameaddress_vector := array_merge(nameaddress_vector, - address_street_word_ids); - END IF; - END IF; - END IF; - IF addr_item.key = 'is_in' THEN - -- is_in items need splitting - isin := regexp_split_to_array(addr_item.value, E'[;,]'); - IF array_upper(isin, 1) IS NOT NULL THEN - FOR i IN 1..array_upper(isin, 1) LOOP - address_street_word_ids := word_ids_from_name(isin[i]); - IF address_street_word_ids is not null THEN - isin_tokens := array_merge(isin_tokens, address_street_word_ids); - END IF; - - -- merge word into address vector - IF NOT %REVERSE-ONLY% THEN - address_street_word_ids := addr_ids_from_name(isin[i]); - IF address_street_word_ids is not null THEN - nameaddress_vector := array_merge(nameaddress_vector, - address_street_word_ids); - END IF; - END IF; - END LOOP; - END IF; - END IF; - END LOOP; - END IF; - IF NOT %REVERSE-ONLY% THEN - nameaddress_vector := array_merge(nameaddress_vector, isin_tokens); - END IF; - --- RAISE WARNING 'ISIN: %', isin_tokens; - - -- Process area matches - location_rank_search := 0; - location_distance := 0; - location_parent := NULL; - -- added ourself as address already - address_havelevel[NEW.rank_address] := true; - --DEBUG: RAISE WARNING ' getNearFeatures(%,''%'',%,''%'')',NEW.partition, NEW.centroid, search_maxrank, isin_tokens; - FOR location IN - SELECT * from getNearFeatures(NEW.partition, - CASE WHEN NEW.rank_search >= 26 + SELECT * FROM insert_addresslines(NEW.place_id, NEW.partition, + NEW.rank_search, NEW.address, + CASE WHEN NEW.rank_search >= 26 AND NEW.rank_search < 30 - THEN NEW.geometry - ELSE NEW.centroid END, - search_maxrank, isin_tokens) - LOOP - IF location.rank_address != location_rank_search THEN - location_rank_search := location.rank_address; - IF location.isguess THEN - location_distance := location.distance * 1.5; - ELSE - IF location.rank_address <= 12 THEN - -- for county and above, if we have an area consider that exact - -- (It would be nice to relax the constraint for places close to - -- the boundary but we'd need the exact geometry for that. Too - -- expensive.) - location_distance = 0; - ELSE - -- Below county level remain slightly fuzzy. - location_distance := location.distance * 0.5; - END IF; - END IF; - ELSE - CONTINUE WHEN location.keywords <@ location_keywords; - END IF; - - IF location.distance < location_distance OR NOT location.isguess THEN - location_keywords := location.keywords; - - 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; + THEN NEW.geometry ELSE NEW.centroid END) + INTO NEW.parent_place_id, NEW.postcode, nameaddress_vector; - -- RAISE WARNING '% isaddress: %', location.place_id, location_isaddress; - -- Add it to the list of search terms - IF NOT %REVERSE-ONLY% THEN - nameaddress_vector := array_merge(nameaddress_vector, location.keywords::integer[]); - END IF; - INSERT INTO place_addressline (place_id, address_place_id, fromarea, isaddress, distance, cached_rank_address) - VALUES (NEW.place_id, location.place_id, true, location_isaddress, location.distance, location.rank_address); - - IF location_isaddress THEN - -- add postcode if we have one - -- (If multiple postcodes are available, we end up with the highest ranking one.) - IF location.postcode is not null THEN - NEW.postcode = location.postcode; - END IF; - - 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; - - --DEBUG: RAISE WARNING ' Terms: (%) %',location, nameaddress_vector; - - END IF; - - END LOOP; - --DEBUG: RAISE WARNING 'address computed'; + --DEBUG: RAISE WARNING 'RETURN insert_addresslines: %, %, %', NEW.parent_place_id, NEW.postcode, nameaddress_vector; IF NEW.address is not null AND NEW.address ? 'postcode' AND NEW.address->'postcode' not similar to '%(,|;)%' THEN