]> git.openstreetmap.org Git - nominatim.git/blobdiff - sql/functions/placex_triggers.sql
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / sql / functions / placex_triggers.sql
index f9d5b60f4bbcf1d45b9b0b2d51ccc07c0e9587ca..2bc7efad826e9ab8461c05a4debd7c0aca8d523d 100644 (file)
@@ -92,7 +92,16 @@ BEGIN
     END IF;
 
     IF fallback THEN
-      IF ST_Area(bbox) < 0.01 THEN
+      IF addr_street is null and addr_place is not null THEN
+        -- The address is attached to a place we don't know. Find the
+        -- nearest place instead.
+        FOR location IN
+          SELECT place_id FROM getNearFeatures(poi_partition, bbox, 26, '{}'::INTEGER[])
+            ORDER BY rank_address DESC, isguess asc, distance LIMIT 1
+        LOOP
+          parent_place_id := location.place_id;
+        END LOOP;
+      ELSEIF ST_Area(bbox) < 0.005 THEN
         -- for smaller features get the nearest road
         SELECT getNearestRoadPlaceId(poi_partition, bbox) INTO parent_place_id;
         --DEBUG: RAISE WARNING 'Checked for nearest way (%)', parent_place_id;
@@ -224,7 +233,7 @@ LANGUAGE plpgsql STABLE;
 -- \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.
+-- \param geometry      Geometry to which the address objects should be close.
 --
 -- \retval parent_place_id  Place_id of the address object that is the direct
 --                          ancestor.
@@ -281,23 +290,6 @@ BEGIN
         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);
@@ -417,7 +409,12 @@ BEGIN
 
       NEW.name := hstore('ref', NEW.address->'postcode');
 
-    ELSEIF NEW.class = 'boundary' AND NOT is_area THEN
+    ELSEIF NEW.class = 'highway' AND is_area AND NEW.name is null
+           AND NEW.extratags ? 'area' AND NEW.extratags->'area' = 'yes'
+    THEN
+        RETURN NULL;
+    ELSEIF NEW.class = 'boundary' AND NOT is_area
+    THEN
         RETURN NULL;
     ELSEIF NEW.class = 'boundary' AND NEW.type = 'administrative'
            AND NEW.admin_level <= 4 AND NEW.osm_type = 'W'
@@ -541,6 +538,9 @@ DECLARE
 
   name_vector INTEGER[];
   nameaddress_vector INTEGER[];
+  addr_nameaddress_vector INTEGER[];
+
+  inherited_address HSTORE;
 
   linked_node_id BIGINT;
   linked_importance FLOAT;
@@ -574,11 +574,27 @@ BEGIN
          where linked_place_id = NEW.place_id;
   -- update not necessary for osmline, cause linked_place_id does not exist
 
+  NEW.extratags := NEW.extratags - 'linked_place'::TEXT;
+
   IF NEW.linked_place_id is not null THEN
     --DEBUG: RAISE WARNING 'place already linked to %', NEW.linked_place_id;
     RETURN NEW;
   END IF;
 
+  -- Postcodes are just here to compute the centroids. They are not searchable
+  -- unless they are a boundary=postal_code.
+  -- There was an error in the style so that boundary=postal_code used to be
+  -- imported as place=postcode. That's why relations are allowed to pass here.
+  -- This can go away in a couple of versions.
+  IF NEW.class = 'place'  and NEW.type = 'postcode' and NEW.osm_type != 'R' THEN
+    RETURN NEW;
+  END IF;
+
+  -- Speed up searches - just use the centroid of the feature
+  -- cheaper but less acurate
+  NEW.centroid := ST_PointOnSurface(NEW.geometry);
+  --DEBUG: RAISE WARNING 'Computing preliminary centroid at %',ST_AsText(NEW.centroid);
+
   -- recompute the ranks, they might change when linking changes
   SELECT * INTO NEW.rank_search, NEW.rank_address
     FROM compute_place_rank(NEW.country_code,
@@ -589,8 +605,10 @@ BEGIN
                             (NEW.extratags->'capital') = 'yes',
                             NEW.address->'postcode');
   -- We must always increase the address level relative to the admin boundary.
-  IF NEW.class = 'boundary' and NEW.type = 'administrative' THEN
-    parent_address_level := get_parent_address_level(NEW.geometry, NEW.admin_level);
+  IF NEW.class = 'boundary' and NEW.type = 'administrative'
+     and NEW.osm_type = 'R' and NEW.rank_address > 0
+  THEN
+    parent_address_level := get_parent_address_level(NEW.centroid, NEW.admin_level);
     IF parent_address_level >= NEW.rank_address THEN
       IF parent_address_level >= 24 THEN
         NEW.rank_address := 25;
@@ -625,16 +643,11 @@ BEGIN
       addr_street := NEW.address->'street';
       addr_place := NEW.address->'place';
 
-      IF NEW.address ? 'postcode' and NEW.address->'postcode' not similar to '%(,|;)%' THEN
+      IF NEW.address ? 'postcode' and NEW.address->'postcode' not similar to '%(:|,|;)%' THEN
         i := getorcreate_postcode_id(NEW.address->'postcode');
       END IF;
   END IF;
 
-  -- Speed up searches - just use the centroid of the feature
-  -- cheaper but less acurate
-  NEW.centroid := ST_PointOnSurface(NEW.geometry);
-  --DEBUG: RAISE WARNING 'Computing preliminary centroid at %',ST_AsText(NEW.centroid);
-
   NEW.postcode := null;
 
   -- recalculate country and partition
@@ -690,13 +703,14 @@ BEGIN
 
   -- ---------------------------------------------------------------------------
   -- 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
+  IF NEW.rank_search > 27 THEN
 
     --DEBUG: RAISE WARNING 'finding street for % %', NEW.osm_type, NEW.osm_id;
     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
+    inherited_address := ''::HSTORE;
     IF NEW.osm_type = 'N' AND addr_street IS NULL AND addr_place IS NULL
        AND NEW.housenumber IS NULL THEN
       FOR location IN
@@ -711,6 +725,7 @@ BEGIN
         NEW.housenumber := location.address->'housenumber';
         addr_street := location.address->'street';
         addr_place := location.address->'place';
+        inherited_address := location.address;
       END LOOP;
     END IF;
 
@@ -741,33 +756,26 @@ BEGIN
         NEW.postcode := get_nearest_postcode(NEW.country_code, NEW.geometry);
       END IF;
 
-      -- If there is no name it isn't searchable, don't bother to create a search record
-      IF NEW.name is NULL THEN
-        --DEBUG: RAISE WARNING 'Not a searchable place % %', NEW.osm_type, NEW.osm_id;
-        return NEW;
-      END IF;
+      IF NEW.name is not NULL THEN
+          NEW.name := add_default_place_name(NEW.country_code, NEW.name);
+          name_vector := make_keywords(NEW.name);
 
-      NEW.name := add_default_place_name(NEW.country_code, NEW.name);
-      name_vector := make_keywords(NEW.name);
+          IF NEW.rank_search <= 25 and NEW.rank_address > 0 THEN
+            result := add_location(NEW.place_id, NEW.country_code, NEW.partition,
+                                   name_vector, NEW.rank_search, NEW.rank_address,
+                                   upper(trim(NEW.address->'postcode')), NEW.geometry);
+            --DEBUG: RAISE WARNING 'Place added to location table';
+          END IF;
 
-      -- Performance, it would be more acurate to do all the rest of the import
-      -- process but it takes too long
-      -- Just be happy with inheriting from parent road only
-      IF NEW.rank_search <= 25 and NEW.rank_address > 0 THEN
-        result := add_location(NEW.place_id, NEW.country_code, NEW.partition, name_vector, NEW.rank_search, NEW.rank_address, upper(trim(NEW.address->'postcode')), NEW.geometry);
-        --DEBUG: RAISE WARNING 'Place added to location table';
       END IF;
 
-      result := insertSearchName(NEW.partition, NEW.place_id, name_vector,
-                                 NEW.rank_search, NEW.rank_address, NEW.geometry);
-
       IF NOT %REVERSE-ONLY% THEN
-          -- Merge address from parent
-          SELECT array_merge(s.name_vector, s.nameaddress_vector)
-            INTO nameaddress_vector
-            FROM search_name s
-            WHERE s.place_id = NEW.parent_place_id;
+        SELECT * INTO name_vector, nameaddress_vector
+          FROM create_poi_search_terms(NEW.parent_place_id,
+                                       inherited_address || NEW.address,
+                                       NEW.housenumber, name_vector);
 
+        IF array_length(name_vector, 1) is not NULL THEN
           INSERT INTO search_name (place_id, search_rank, address_rank,
                                    importance, country_code, name_vector,
                                    nameaddress_vector, centroid)
@@ -776,8 +784,9 @@ BEGIN
                          nameaddress_vector, NEW.centroid);
           --DEBUG: RAISE WARNING 'Place added to search table';
         END IF;
+      END IF;
 
-      return NEW;
+      RETURN NEW;
     END IF;
 
   END IF;
@@ -925,10 +934,14 @@ DECLARE
 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.linked_place_id is null THEN
+    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;
+  ELSE
+    update placex set indexed_status = 2 where place_id = OLD.linked_place_id and indexed_status = 0;
+  END IF;
 
   IF OLD.rank_address < 30 THEN