]> git.openstreetmap.org Git - nominatim.git/commitdiff
Merge remote-tracking branch 'upstream/master'
authorSarah Hoffmann <lonvia@denofr.de>
Wed, 18 Nov 2020 07:58:38 +0000 (08:58 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Wed, 18 Nov 2020 07:58:38 +0000 (08:58 +0100)
.github/actions/setup-postgresql/action.yml
nominatim/nominatim.py
sql/functions/address_lookup.sql
sql/functions/normalization.sql
sql/functions/placex_triggers.sql
sql/functions/ranking.sql
sql/partition-functions.src.sql
sql/partition-tables.src.sql
test/bdd/db/import/addressing.feature
test/bdd/db/import/linking.feature
test/bdd/db/import/search_name.feature

index a5716be5b445ea668b204c4f654bb85d4bc4888b..98086f2d0a40acd0bab26b47a95e4d05e27afbfc 100644 (file)
@@ -5,7 +5,9 @@ runs:
 
     steps:
         - name: Install postgis
-          run: sudo apt-get install -y -qq postgresql-13-postgis-3 postgresql-13-postgis-3-scripts postgresql-server-dev-13
+          run: |
+            sudo apt-get update -qq
+            sudo apt-get install -y -qq postgresql-13-postgis-3 postgresql-13-postgis-3-scripts postgresql-server-dev-13
           shell: bash
 
         - name: Adapt postgresql configuration
index 0819bb11fa1891e2054f8ce3a349d27cad3a9c8b..b20673d2a0fbef3c71ff2f2d93af811f8df2062d 100755 (executable)
@@ -135,19 +135,19 @@ class Indexer(object):
         for rank in range(max(1, self.minrank), self.maxrank):
             self.index(RankRunner(rank))
 
-
         if self.maxrank == 30:
             self.index(RankRunner(0))
             self.index(InterpolationRunner(), 20)
-
-        self.index(RankRunner(self.maxrank), 20)
+            self.index(RankRunner(self.maxrank), 20)
+        else:
+            self.index(RankRunner(self.maxrank))
 
     def index(self, obj, batch=1):
         """ Index a single rank or table. `obj` describes the SQL to use
             for indexing. `batch` describes the number of objects that
             should be processed with a single SQL statement
         """
-        log.warning("Starting {}".format(obj.name()))
+        log.warning("Starting %s (using batch size %s)", obj.name(), batch)
 
         cur = self.conn.cursor()
         cur.execute(obj.sql_count_objects())
index 381b712510c116046fa8c944002e70287bd71816..de6fe1d17de5edf150d09f0a3fe7f892d48da3dc 100644 (file)
@@ -90,7 +90,7 @@ DECLARE
   for_place_id BIGINT;
   result TEXT[];
   search TEXT[];
-  found INTEGER;
+  current_rank_address INTEGER;
   location RECORD;
   countrylocation RECORD;
   searchcountrycode varchar(2);
@@ -103,7 +103,7 @@ DECLARE
   search_unlisted_place TEXT;
   countryname HSTORE;
 BEGIN
-  -- The place ein question might not have a direct entry in place_addressline.
+  -- The place in question might not have a direct entry in place_addressline.
   -- Look for the parent of such places then and save if in for_place_id.
 
   postcode_isexact := false;
@@ -177,9 +177,8 @@ BEGIN
 
 --RAISE WARNING '% % % %',searchcountrycode, searchhousenumber, searchpostcode;
 
-  found := 1000; -- the lowest rank_address included
+  -- --- Return the record for the base entry.
 
-  -- Return the record for the base entry.
   FOR location IN
     SELECT placex.place_id, osm_type, osm_id, name,
            coalesce(extratags->'linked_place', extratags->'place') as place_type,
@@ -206,9 +205,12 @@ BEGIN
                            location.admin_level, true, location.isaddress,
                            location.rank_address, location.distance)::addressline;
     RETURN NEXT countrylocation;
-    found := location.rank_address;
+
+    current_rank_address := location.rank_address;
   END LOOP;
 
+  -- --- Return records for address parts.
+
   FOR location IN
     SELECT placex.place_id, osm_type, osm_id, name, class, type,
            coalesce(extratags->'linked_place', extratags->'place') as place_type,
@@ -216,14 +218,15 @@ BEGIN
            CASE WHEN rank_address = 11 THEN 5 ELSE rank_address END as rank_address,
            distance, country_code, postcode
       FROM place_addressline join placex on (address_place_id = placex.place_id)
-      WHERE place_addressline.place_id = for_place_id
+      WHERE place_addressline.place_id IN (for_place_id, in_place_id)
             AND linked_place_id is null
             AND (placex.country_code IS NULL OR searchcountrycode IS NULL
                  OR placex.country_code = searchcountrycode)
-      ORDER BY rank_address desc, isaddress desc, fromarea desc,
+      ORDER BY rank_address desc, (place_addressline.place_id = in_place_id) desc,
+               isaddress desc, fromarea desc,
                distance asc, rank_search desc
   LOOP
---RAISE WARNING '%',location;
+    -- RAISE WARNING '%',location;
     IF searchcountrycode IS NULL AND location.country_code IS NOT NULL THEN
       searchcountrycode := location.country_code;
     END IF;
@@ -243,17 +246,21 @@ BEGIN
                            location.name, location.class, location.type,
                            location.place_type,
                            location.admin_level, location.fromarea,
-                           location.isaddress, location.rank_address,
+                           location.isaddress and location.rank_address != current_rank_address,
+                           location.rank_address,
                            location.distance)::addressline;
     RETURN NEXT countrylocation;
-    found := location.rank_address;
+
+    IF location.isaddress THEN
+      current_rank_address := location.rank_address;
+    END IF;
   END LOOP;
 
   -- If no country was included yet, add the name information from country_name.
-  IF found > 4 THEN
+  IF current_rank_address > 4 THEN
     SELECT name FROM country_name
       WHERE country_code = searchcountrycode LIMIT 1 INTO countryname;
---RAISE WARNING '% % %',found,searchcountrycode,countryname;
+--RAISE WARNING '% % %',current_rank_address,searchcountrycode,countryname;
     IF countryname IS NOT NULL THEN
       location := ROW(null, null, null, countryname, 'place', 'country', NULL,
                       null, true, true, 4, 0)::addressline;
index 71b14ee5109aa198f510993247073df754cafdc5..4aea0e9ba3673854dd4cf8ed7dea492916600b66 100644 (file)
@@ -207,19 +207,31 @@ CREATE OR REPLACE FUNCTION addr_ids_from_name(lookup_word TEXT)
   RETURNS INTEGER[]
   AS $$
 DECLARE
-  lookup_token TEXT;
+  words TEXT[];
   id INTEGER;
   return_word_id INTEGER[];
+  word_ids INTEGER[];
+  j INTEGER;
 BEGIN
-  lookup_token := make_standard_name(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_id;
-  IF return_word_id IS NULL THEN
-    id := nextval('seq_word');
-    INSERT INTO word VALUES (id, lookup_token, null, null, null, null, 0);
-    return_word_id = ARRAY[id];
+  words := string_to_array(make_standard_name(lookup_word), ' ');
+  IF array_upper(words, 1) IS NOT NULL THEN
+    FOR j IN 1..array_upper(words, 1) LOOP
+      IF (words[j] != '') THEN
+        SELECT array_agg(word_id) INTO word_ids
+          FROM word
+         WHERE word_token = words[j] and class is null and type is null;
+
+        IF word_ids IS NULL THEN
+          id := nextval('seq_word');
+          INSERT INTO word VALUES (id, words[j], null, null, null, null, 0);
+          return_word_id := return_word_id || id;
+        ELSE
+          return_word_id := array_merge(return_word_id, word_ids);
+        END IF;
+      END IF;
+    END LOOP;
   END IF;
+
   RETURN return_word_id;
 END;
 $$
@@ -414,10 +426,14 @@ $$
 LANGUAGE plpgsql;
 
 
-CREATE OR REPLACE FUNCTION create_poi_search_terms(parent_place_id BIGINT,
+CREATE OR REPLACE FUNCTION create_poi_search_terms(obj_place_id BIGINT,
+                                                   in_partition SMALLINT,
+                                                   parent_place_id BIGINT,
                                                    address HSTORE,
+                                                   country TEXT,
                                                    housenumber TEXT,
                                                    initial_name_vector INTEGER[],
+                                                   geometry GEOMETRY,
                                                    OUT name_vector INTEGER[],
                                                    OUT nameaddress_vector INTEGER[])
   AS $$
@@ -427,34 +443,60 @@ DECLARE
   addr_place_ids INTEGER[];
 
   addr_item RECORD;
+  parent_address_place_ids BIGINT[];
+  filtered_address HSTORE;
 BEGIN
-  -- Compute all search terms from the addr: tags.
   nameaddress_vector := '{}'::INTEGER[];
 
-  IF address IS NOT NULL THEN
-    FOR addr_item IN SELECT * FROM each(address)
+  SELECT s.name_vector, s.nameaddress_vector
+    INTO parent_name_vector, parent_address_vector
+    FROM search_name s
+    WHERE s.place_id = parent_place_id;
+
+  -- Find all address tags that don't appear in the parent search names.
+  SELECT hstore(array_agg(ARRAY[k, v])) INTO filtered_address
+    FROM (SELECT skeys(address) as k, svals(address) as v) a
+   WHERE not addr_ids_from_name(v) && parent_address_vector
+         AND k not in ('country', 'street', 'place', 'postcode',
+                       'housenumber', 'streetnumber', 'conscriptionnumber');
+
+  -- Compute all search terms from the addr: tags.
+  IF filtered_address IS NOT NULL THEN
+    FOR addr_item IN
+      SELECT * FROM
+        get_places_for_addr_tags(in_partition, geometry, filtered_address, country)
     LOOP
-      IF addr_item.key IN ('city', 'tiger:county', 'state', 'suburb', 'province',
-                           'district', 'region', 'county', 'municipality',
-                           'hamlet', 'village', 'subdistrict', 'town',
-                           'neighbourhood', 'quarter', 'parish')
-      THEN
-          nameaddress_vector := array_merge(nameaddress_vector,
-                                            addr_ids_from_name(addr_item.value));
-      END IF;
+        IF addr_item.place_id is null THEN
+            nameaddress_vector := array_merge(nameaddress_vector,
+                                              addr_item.keywords);
+            CONTINUE;
+        END IF;
+
+        IF parent_address_place_ids is null THEN
+            SELECT array_agg(parent_place_id) INTO parent_address_place_ids
+              FROM place_addressline
+             WHERE place_id = parent_place_id;
+        END IF;
+
+        IF not parent_address_place_ids @> ARRAY[addr_item.place_id] THEN
+            nameaddress_vector := array_merge(nameaddress_vector,
+                                              addr_item.keywords);
+
+            INSERT INTO place_addressline (place_id, address_place_id, fromarea,
+                                           isaddress, distance, cached_rank_address)
+            VALUES (obj_place_id, addr_item.place_id, not addr_item.isguess,
+                    true, addr_item.distance, addr_item.rank_address);
+        END IF;
     END LOOP;
   END IF;
 
+
   -- If the POI is named, simply mix in all address terms and be done.
   IF array_length(initial_name_vector, 1) is not NULL THEN
     -- Cheating here by not recomputing all terms but simply using the ones
     -- from the parent object.
-    SELECT array_merge(s.name_vector, s.nameaddress_vector)
-      INTO parent_address_vector
-      FROM search_name s
-      WHERE s.place_id = parent_place_id;
-
     name_vector := initial_name_vector;
+    nameaddress_vector := array_merge(nameaddress_vector, parent_name_vector);
     nameaddress_vector := array_merge(nameaddress_vector, parent_address_vector);
 
     IF not address ? 'street' and address ? 'place' THEN
@@ -475,11 +517,6 @@ BEGIN
     RETURN;
   END IF;
 
-  SELECT s.name_vector, s.nameaddress_vector
-    INTO parent_name_vector, parent_address_vector
-    FROM search_name s
-    WHERE s.place_id = parent_place_id;
-
   -- Check if the parent covers all address terms.
   -- If not, create a search name entry with the house number as the name.
   -- This is unusual for the search_name table but prevents that the place
@@ -493,16 +530,14 @@ BEGIN
     addr_place_ids := addr_ids_from_name(address->'place');
     IF not addr_place_ids <@ parent_name_vector THEN
       -- addr:place tag exists without a corresponding place. Mix in addr:place
-      -- in the address and drop the name from the parent. This would only be
-      -- the street name of the nearest street.
-      nameaddress_vector := array_merge(nameaddress_vector, addr_place_ids);
+      -- in the address.
       name_vector := ARRAY[getorcreate_name_id(housenumber)];
+      nameaddress_vector := array_merge(nameaddress_vector, addr_place_ids);
     END IF;
-  ELSE
-    nameaddress_vector := array_merge(nameaddress_vector, parent_name_vector);
   END IF;
 
-  -- The address vector always gets merged in.
+  -- Merge the parent name and address.
+  nameaddress_vector := array_merge(nameaddress_vector, parent_name_vector);
   nameaddress_vector := array_merge(nameaddress_vector, parent_address_vector);
 
 END;
index 6848140ad44e249fcacf41eb6768abfbb9b347c8..7d6352b4eda6ea2bdd7fe0dfc6475ba710065f42 100644 (file)
@@ -138,6 +138,7 @@ DECLARE
 BEGIN
   IF bnd.rank_search >= 26 or bnd.rank_address = 0
      or ST_GeometryType(bnd.geometry) NOT IN ('ST_Polygon','ST_MultiPolygon')
+     or bnd.type IN ('postcode', 'postal_code')
   THEN
     RETURN NULL;
   END IF;
@@ -254,6 +255,7 @@ CREATE OR REPLACE FUNCTION insert_addresslines(obj_place_id BIGINT,
                                                maxrank SMALLINT,
                                                address HSTORE,
                                                geometry GEOMETRY,
+                                               country TEXT,
                                                OUT parent_place_id BIGINT,
                                                OUT postcode TEXT,
                                                OUT nameaddress_vector INT[])
@@ -265,45 +267,49 @@ DECLARE
   current_boundary GEOMETRY := NULL;
   current_node_area GEOMETRY := NULL;
 
-  location RECORD;
-  addr_item RECORD;
+  parent_place_rank INT := 0;
+  addr_place_ids BIGINT[];
 
-  isin_tokens INT[];
+  location RECORD;
 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));
+  address_havelevel := array_fill(false, ARRAY[maxrank]);
+
+  FOR location IN
+    SELECT * FROM get_places_for_addr_tags(partition, geometry,
+                                                   address, country)
+    ORDER BY rank_address, distance, isguess desc
+  LOOP
+    IF NOT %REVERSE-ONLY% THEN
+      nameaddress_vector := array_merge(nameaddress_vector,
+                                        location.keywords::int[]);
+    END IF;
+
+    IF location.place_id is not null THEN
+      location_isaddress := not address_havelevel[location.rank_address];
+      IF not address_havelevel[location.rank_address] THEN
+        address_havelevel[location.rank_address] := true;
+        IF parent_place_rank < location.rank_address THEN
+          parent_place_id := location.place_id;
+          parent_place_rank := location.rank_address;
         END IF;
       END IF;
-    END LOOP;
-  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..maxrank LOOP
-    address_havelevel[i] := false;
+      INSERT INTO place_addressline (place_id, address_place_id, fromarea,
+                                     isaddress, distance, cached_rank_address)
+        VALUES (obj_place_id, location.place_id, not location.isguess,
+                true, location.distance, location.rank_address);
+
+      addr_place_ids := array_append(addr_place_ids, location.place_id);
+    END IF;
   END LOOP;
 
   FOR location IN
     SELECT * FROM getNearFeatures(partition, geometry, maxrank)
-    ORDER BY rank_address, isin_tokens && keywords desc, isguess asc,
+    WHERE addr_place_ids is null or not addr_place_ids @> ARRAY[place_id]
+    ORDER BY rank_address, isguess asc,
              distance *
                CASE WHEN rank_address = 16 AND rank_search = 15 THEN 0.2
                     WHEN rank_address = 16 AND rank_search = 16 THEN 0.25
@@ -808,13 +814,17 @@ BEGIN
 
       END IF;
 
-      IF NOT %REVERSE-ONLY% THEN
+      IF array_length(name_vector, 1) is not NULL
+         OR inherited_address is not NULL OR NEW.address is not NULL
+      THEN
         SELECT * INTO name_vector, nameaddress_vector
-          FROM create_poi_search_terms(NEW.parent_place_id,
+          FROM create_poi_search_terms(NEW.place_id,
+                                       NEW.partition, NEW.parent_place_id,
                                        inherited_address || NEW.address,
-                                       NEW.housenumber, name_vector);
+                                       NEW.country_code, NEW.housenumber,
+                                       name_vector, NEW.centroid);
 
-        IF array_length(name_vector, 1) is not NULL THEN
+        IF not %REVERSE-ONLY% AND 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)
@@ -920,7 +930,8 @@ BEGIN
                                     NEW.address,
                                     CASE WHEN (NEW.rank_address = 0 or
                                                NEW.rank_search between 26 and 29)
-                                         THEN NEW.geometry ELSE NEW.centroid END)
+                                         THEN NEW.geometry ELSE NEW.centroid END,
+                                    NEW.country_code)
     INTO NEW.parent_place_id, NEW.postcode, nameaddress_vector;
 
   --DEBUG: RAISE WARNING 'RETURN insert_addresslines: %, %, %', NEW.parent_place_id, NEW.postcode, nameaddress_vector;
index a84269fe6730669b6c805a0bb632b645c87f1199..51dcd0d03dd76d937719fb1b45ce00ff17e89307 100644 (file)
@@ -233,3 +233,50 @@ BEGIN
 END;
 $$
 LANGUAGE plpgsql IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION get_addr_tag_rank(key TEXT, country TEXT,
+                                             OUT from_rank SMALLINT,
+                                             OUT to_rank SMALLINT,
+                                             OUT extent FLOAT)
+  AS $$
+DECLARE
+  ranks RECORD;
+BEGIN
+  from_rank := null;
+
+  FOR ranks IN
+    SELECT * FROM
+      (SELECT l.rank_search, l.rank_address FROM address_levels l
+        WHERE (l.country_code = country or l.country_code is NULL)
+               AND l.class = 'place' AND l.type = key
+        ORDER BY l.country_code LIMIT 1) r
+      WHERE rank_address > 0
+  LOOP
+    extent := reverse_place_diameter(ranks.rank_search);
+
+    IF ranks.rank_address <= 4 THEN
+        from_rank := 4;
+        to_rank := 4;
+    ELSEIF ranks.rank_address <= 9 THEN
+        from_rank := 5;
+        to_rank := 9;
+    ELSEIF ranks.rank_address <= 12 THEN
+        from_rank := 10;
+        to_rank := 12;
+    ELSEIF ranks.rank_address <= 16 THEN
+        from_rank := 13;
+        to_rank := 16;
+    ELSEIF ranks.rank_address <= 21 THEN
+        from_rank := 17;
+        to_rank := 21;
+    ELSEIF ranks.rank_address <= 24 THEN
+        from_rank := 22;
+        to_rank := 24;
+    ELSE
+        from_rank := 25;
+        to_rank := 25;
+    END IF;
+  END LOOP;
+END;
+$$
+LANGUAGE plpgsql IMMUTABLE;
index 97520f99b8441d5fec6f61248afa3572a4d3cb00..1197b3b7337df4cdcbcde5869fbd4d75ec828cd6 100644 (file)
@@ -10,8 +10,8 @@ CREATE TYPE nearfeaturecentr AS (
   centroid GEOMETRY
 );
 
-        -- feature intersects geoemtry
-        -- for areas and linestrings they must touch at least along a line
+-- feature intersects geoemtry
+-- for areas and linestrings they must touch at least along a line
 CREATE OR REPLACE FUNCTION is_relevant_geometry(de9im TEXT, geom_type TEXT)
 RETURNS BOOLEAN
 AS $$
@@ -39,8 +39,10 @@ BEGIN
 
 -- start
   IF in_partition = -partition- THEN
-    FOR r IN 
-      SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(feature, centroid)) as distance, isguess, postcode, centroid
+    FOR r IN
+      SELECT place_id, keywords, rank_address, rank_search,
+             min(ST_Distance(feature, centroid)) as distance,
+             isguess, postcode, centroid
       FROM location_area_large_-partition-
       WHERE geometry && feature
         AND is_relevant_geometry(ST_Relate(geometry, feature), ST_GeometryType(feature))
@@ -58,6 +60,54 @@ END
 $$
 LANGUAGE plpgsql STABLE;
 
+CREATE OR REPLACE FUNCTION get_places_for_addr_tags(in_partition SMALLINT,
+                                                    feature GEOMETRY,
+                                                    address HSTORE, country TEXT)
+  RETURNS SETOF nearfeaturecentr
+  AS $$
+DECLARE
+  r nearfeaturecentr%rowtype;
+  item RECORD;
+BEGIN
+  FOR item IN
+    SELECT (get_addr_tag_rank(key, country)).*, key, name FROM
+      (SELECT skeys(address) as key, svals(address) as name) x
+  LOOP
+   IF item.from_rank is null THEN
+     CONTINUE;
+   END IF;
+
+-- start
+    IF in_partition = -partition- THEN
+        SELECT place_id, keywords, rank_address, rank_search,
+               min(ST_Distance(feature, centroid)) as distance,
+               isguess, postcode, centroid INTO r
+        FROM location_area_large_-partition-
+        WHERE geometry && ST_Expand(feature, item.extent)
+          AND rank_address between item.from_rank and item.to_rank
+          AND word_ids_from_name(item.name) && keywords
+        GROUP BY place_id, keywords, rank_address, rank_search, isguess, postcode, centroid
+        ORDER BY bool_or(ST_Intersects(geometry, feature)), distance LIMIT 1;
+      IF r.place_id is null THEN
+        -- If we cannot find a place for the term, just return the
+        -- search term for the given name. That ensures that the address
+        -- element can still be searched for, even though it will not be
+        -- displayed.
+        RETURN NEXT ROW(null, addr_ids_from_name(item.name), null, null,
+                        null, null, null, null)::nearfeaturecentr;
+      ELSE
+        RETURN NEXT r;
+      END IF;
+      CONTINUE;
+    END IF;
+-- end
+
+    RAISE EXCEPTION 'Unknown partition %', in_partition;
+  END LOOP;
+END;
+$$
+LANGUAGE plpgsql STABLE;
+
 create or replace function deleteLocationArea(in_partition INTEGER, in_place_id BIGINT, in_rank_search INTEGER) RETURNS BOOLEAN AS $$
 DECLARE
 BEGIN
@@ -126,7 +176,7 @@ BEGIN
       INTO parent
       WHERE name_vector && isin_token
             AND centroid && ST_Expand(point, 0.015)
-            AND search_rank between 26 and 27
+            AND address_rank between 26 and 27
       ORDER BY ST_Distance(centroid, point) ASC limit 1;
     RETURN parent;
   END IF;
@@ -153,7 +203,7 @@ BEGIN
       FROM search_name_-partition-
       WHERE name_vector && isin_token
             AND centroid && ST_Expand(point, 0.04)
-            AND search_rank between 16 and 25
+            AND address_rank between 16 and 25
       ORDER BY ST_Distance(centroid, point) ASC limit 1;
     RETURN parent;
   END IF;
@@ -164,7 +214,6 @@ END
 $$
 LANGUAGE plpgsql STABLE;
 
-
 create or replace function insertSearchName(
   in_partition INTEGER, in_place_id BIGINT, in_name_vector INTEGER[],
   in_rank_search INTEGER, in_rank_address INTEGER, in_geometry GEOMETRY)
@@ -175,8 +224,8 @@ BEGIN
   IF in_partition = -partition- THEN
     DELETE FROM search_name_-partition- values WHERE place_id = in_place_id;
     IF in_rank_address > 0 THEN
-      INSERT INTO search_name_-partition- (place_id, search_rank, address_rank, name_vector, centroid)
-        values (in_place_id, in_rank_search, in_rank_address, in_name_vector, in_geometry);
+      INSERT INTO search_name_-partition- (place_id, address_rank, name_vector, centroid)
+        values (in_place_id, in_rank_address, in_name_vector, in_geometry);
     END IF;
     RETURN TRUE;
   END IF;
index 8749243e5f8fb94402685d52463912cd1253a1bf..df2cac70403c067e751f9a77fdea66427986e4ab 100644 (file)
@@ -1,7 +1,6 @@
 drop table IF EXISTS search_name_blank CASCADE;
 CREATE TABLE search_name_blank (
   place_id BIGINT,
-  search_rank smallint,
   address_rank smallint,
   name_vector integer[],
   centroid GEOMETRY(Geometry, 4326)
@@ -15,8 +14,8 @@ CREATE INDEX idx_location_area_large_-partition-_geometry ON location_area_large
 
 CREATE TABLE search_name_-partition- () INHERITS (search_name_blank) {ts:address-data};
 CREATE INDEX idx_search_name_-partition-_place_id ON search_name_-partition- USING BTREE (place_id) {ts:address-index};
-CREATE INDEX idx_search_name_-partition-_centroid_street ON search_name_-partition- USING GIST (centroid) {ts:address-index} where search_rank between 26 and 27;
-CREATE INDEX idx_search_name_-partition-_centroid_place ON search_name_-partition- USING GIST (centroid) {ts:address-index} where search_rank between 2 and 25;
+CREATE INDEX idx_search_name_-partition-_centroid_street ON search_name_-partition- USING GIST (centroid) {ts:address-index} where address_rank between 26 and 27;
+CREATE INDEX idx_search_name_-partition-_centroid_place ON search_name_-partition- USING GIST (centroid) {ts:address-index} where address_rank between 2 and 25;
 
 DROP TABLE IF EXISTS location_road_-partition-;
 CREATE TABLE location_road_-partition- (
index 52f966d807ffb38c140a764e301f05c05965d4a0..9050c19b0923c6cf10d388e7725fd347d0847fa1 100644 (file)
@@ -298,3 +298,102 @@ Feature: Address computation
             | object | address |
             | W1     | W2      |
 
+    Scenario: addr:* tags are honored even when a street is far away from the place
+        Given the grid
+            | 1 |   | 2 |   |   | 5 |
+            |   |   |   | 8 | 9 |   |
+            | 4 |   | 3 |   |   | 6 |
+        And the places
+            | osm | class    | type           | admin | name  | geometry    |
+            | R1  | boundary | administrative | 8     | Left  | (1,2,3,4,1) |
+            | R2  | boundary | administrative | 8     | Right | (2,3,6,5,2) |
+        And the places
+            | osm | class   | type    | addr+city | geometry |
+            | W1  | highway | primary | Left      | 8,9      |
+            | W2  | highway | primary | Right     | 8,9      |
+        When importing
+        Then place_addressline contains
+           | object | address | isaddress |
+           | W1     | R1      | True      |
+           | W1     | R2      | False     |
+           | W2     | R2      | True      |
+        And place_addressline doesn't contain
+           | object | address |
+           | W2     | R1      |
+
+
+    Scenario: addr:* tags are honored even when a POI is far away from the place
+        Given the grid
+            | 1 |   | 2 |   |   | 5 |
+            |   |   |   | 8 | 9 |   |
+            | 4 |   | 3 |   |   | 6 |
+        And the places
+            | osm | class    | type           | admin | name  | geometry    |
+            | R1  | boundary | administrative | 8     | Left  | (1,2,3,4,1) |
+            | R2  | boundary | administrative | 8     | Right | (2,3,6,5,2) |
+        And the places
+            | osm | class   | type    | name      | addr+city | geometry |
+            | W1  | highway | primary | Wonderway | Right     | 8,9      |
+            | N1  | amenity | cafe    | Bolder    | Left      | 9        |
+        When importing
+        Then place_addressline contains
+           | object | address | isaddress |
+           | W1     | R2      | True      |
+           | N1     | R1      | True      |
+        And place_addressline doesn't contain
+           | object | address |
+           | W1     | R1      |
+        When searching for "Bolder"
+        Then results contain
+           | osm_type | osm_id | name                    |
+           | N        | 1      | Bolder, Wonderway, Left |
+
+    Scenario: addr:* tags do not produce addresslines when the parent has the address part
+        Given the grid
+            | 1 |   |   | 5 |
+            |   | 8 | 9 |   |
+            | 4 |   |   | 6 |
+        And the places
+            | osm | class    | type           | admin | name  | geometry    |
+            | R1  | boundary | administrative | 8     | Outer | (1,5,6,4,1) |
+        And the places
+            | osm | class   | type    | name      | addr+city | geometry |
+            | W1  | highway | primary | Wonderway | Outer     | 8,9      |
+            | N1  | amenity | cafe    | Bolder    | Outer     | 9        |
+        When importing
+        Then place_addressline contains
+           | object | address | isaddress |
+           | W1     | R1      | True      |
+        And place_addressline doesn't contain
+           | object | address |
+           | N1     | R1      |
+        When searching for "Bolder"
+        Then results contain
+           | osm_type | osm_id | name                     |
+           | N        | 1      | Bolder, Wonderway, Outer |
+
+    Scenario: addr:* tags on outside do not produce addresslines when the parent has the address part
+        Given the grid
+            | 1 |   | 2 |   |   | 5 |
+            |   |   |   | 8 | 9 |   |
+            | 4 |   | 3 |   |   | 6 |
+        And the places
+            | osm | class    | type           | admin | name  | geometry    |
+            | R1  | boundary | administrative | 8     | Left  | (1,2,3,4,1) |
+            | R2  | boundary | administrative | 8     | Right | (2,3,6,5,2) |
+        And the places
+            | osm | class   | type    | name      | addr+city | geometry |
+            | W1  | highway | primary | Wonderway | Left      | 8,9      |
+            | N1  | amenity | cafe    | Bolder    | Left      | 9        |
+        When importing
+        Then place_addressline contains
+           | object | address | isaddress |
+           | W1     | R1      | True      |
+           | W1     | R2      | False     |
+        And place_addressline doesn't contain
+           | object | address |
+           | N1     | R1      |
+        When searching for "Bolder"
+        Then results contain
+           | osm_type | osm_id | name                    |
+           | N        | 1      | Bolder, Wonderway, Left |
index fa96e5b31e94b12ba1b0399e05b8d4d4e864b756..1e0d131a385abf896ca098ab429e0af5ea44b5d3 100644 (file)
@@ -14,7 +14,22 @@ Feature: Linking of places
          | R13     | - |
          | N256    | - |
 
-    Scenario: Waterways are linked when in waterway relations
+    Scenario: Postcode areas cannot be linked
+        Given the grid
+         | 1 |   | 2 |
+         |   | 9 |   |
+         | 4 |   | 3 |
+        And the named places
+         | osm | class    | type        | addr+postcode  | extra+wikidata | geometry    |
+         | R13 | boundary | postal_code | 123            | Q87493         | (1,2,3,4,1) |
+         | N25 | place    | suburb      | 123            | Q87493         | 9 |
+        When importing
+        Then placex contains
+         | object | linked_place_id |
+         | R13    | - |
+         | N25    | - |
+
+     Scenario: Waterways are linked when in waterway relations
         Given the scene split-road
         And the places
          | osm | class    | type  | name  | geometry |
index a0a53911f86d221579f1a2cf6ec515ddef5c4296..30c430a6b4503e33da91aa4d53a04eb8e9db4d25 100644 (file)
@@ -30,7 +30,24 @@ Feature: Creation of search terms
          | osm_type | osm_id | name |
          | N        | 1      | 23, Rose Street |
 
-    Scenario: Unnamed POI has no search entry when it has known addr: tags
+    Scenario: Searching for unknown addr: tags also works for multiple words
+        Given the scene roads-with-pois
+        And the places
+         | osm | class   | type        | housenr | addr+city        | geometry |
+         | N1  | place   | house       | 23      | Little Big Town  | :p-N1 |
+        And the places
+         | osm | class   | type        | name+name   | geometry |
+         | W1  | highway | residential | Rose Street | :w-north |
+        When importing
+        Then search_name contains
+         | object | name_vector | nameaddress_vector |
+         | N1     | #23         | Rose Street, Little, Big, Town |
+        When searching for "23 Rose Street, Little Big Town"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | 23, Rose Street |
+
+     Scenario: Unnamed POI has no search entry when it has known addr: tags
         Given the scene roads-with-pois
         And the places
          | osm | class   | type        | housenr | addr+city | geometry |
@@ -56,7 +73,7 @@ Feature: Creation of search terms
         When importing
         Then search_name has no entry for N1
 
-    Scenario: Unnamed POIs doesn't inherit parent name when unknown addr:place is present
+    Scenario: Unnamed POIs inherit parent name when unknown addr:place is present
         Given the scene roads-with-pois
         And the places
          | osm | class   | type        | housenr | addr+place | geometry |
@@ -66,15 +83,18 @@ Feature: Creation of search terms
          | W1  | highway | residential | Rose Street  | :w-north |
          | N2  | place   | city        | Strange Town | :p-N1 |
         When importing
+        Then placex contains
+         | object | parent_place_id |
+         | N1     | N2              |
         Then search_name contains
          | object | name_vector | nameaddress_vector |
-         | N1     | #23         | Walltown |
+         | N1     | #23         | Walltown, Strange, Town |
         When searching for "23 Rose Street"
         Then exactly 1 results are returned
         And results contain
          | osm_type | osm_id | name |
          | W        | 1      | Rose Street, Strange Town |
-        When searching for "23 Walltown"
+        When searching for "23 Walltown, Strange Town"
         Then results contain
          | osm_type | osm_id | name |
          | N        | 1      | 23, Walltown, Strange Town |
@@ -185,20 +205,19 @@ Feature: Creation of search terms
          | object | name_vector | nameaddress_vector |
          | N1     | foo         | the road |
 
-    Scenario: Some addr: tags are added to address when the name exists
+    Scenario: Some addr: tags are added to address
         Given the scene roads-with-pois
         And the places
          | osm | class   | type        | name     | geometry |
-         | N1  | place   | state       | new york | 80 80 |
          | N2  | place   | city        | bonn     | 81 81 |
          | N3  | place   | suburb      | smalltown| 80 81 |
         And the named places
-         | osm | class   | type    | addr+city | addr+state | addr+suburb | geometry |
-         | W1  | highway | service | bonn      | New York   | Smalltown   | :w-north |
+         | osm | class   | type    | addr+city | addr+municipality | addr+suburb | geometry |
+         | W1  | highway | service | bonn      | New York          | Smalltown   | :w-north |
         When importing
         Then search_name contains
          | object | nameaddress_vector |
-         | W1     | bonn, new york, smalltown |
+         | W1     | bonn, new, york, smalltown |
 
     Scenario: A known addr:* tag is added even if the name is unknown
         Given the scene roads-with-pois