diff --git a/sql/functions.sql b/sql/functions.sql index 61228c42..be67cf01 100644 --- a/sql/functions.sql +++ b/sql/functions.sql @@ -1679,7 +1679,12 @@ BEGIN -- added ourself as address already address_havelevel[NEW.rank_address] := true; -- RAISE WARNING ' getNearFeatures(%,''%'',%,''%'')',NEW.partition, place_centroid, search_maxrank, isin_tokens; - FOR location IN SELECT * from getNearFeatures(NEW.partition, place_centroid, search_maxrank, isin_tokens) LOOP + FOR location IN + SELECT * from getNearFeatures(NEW.partition, + CASE WHEN NEW.rank_search >= 26 THEN NEW.geometry + ELSE place_centroid END, + search_maxrank, isin_tokens) + LOOP --RAISE WARNING ' AREA: %',location; diff --git a/sql/partition-functions.src.sql b/sql/partition-functions.src.sql index a0181c0a..46dc6137 100644 --- a/sql/partition-functions.src.sql +++ b/sql/partition-functions.src.sql @@ -1,4 +1,4 @@ -create or replace function getNearFeatures(in_partition INTEGER, point GEOMETRY, maxrank INTEGER, isin_tokens INT[]) RETURNS setof nearfeaturecentr AS $$ +create or replace function getNearFeatures(in_partition INTEGER, feature GEOMETRY, maxrank INTEGER, isin_tokens INT[]) RETURNS setof nearfeaturecentr AS $$ DECLARE r nearfeaturecentr%rowtype; BEGIN @@ -6,14 +6,14 @@ BEGIN -- start IF in_partition = -partition- THEN FOR r IN - SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(point, centroid)) as distance, isguess, centroid FROM ( - SELECT * FROM location_area_large_-partition- WHERE ST_Contains(geometry, point) and rank_search < maxrank + SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(feature, centroid)) as distance, isguess, centroid FROM ( + SELECT * FROM location_area_large_-partition- WHERE ST_Intersects(geometry, feature) and rank_search < maxrank UNION ALL - SELECT * FROM location_area_country WHERE ST_Contains(geometry, point) and rank_search < maxrank + SELECT * FROM location_area_country WHERE ST_Intersects(geometry, feature) and rank_search < maxrank ) as location_area GROUP BY place_id, keywords, rank_address, rank_search, isguess, centroid ORDER BY rank_address, isin_tokens && keywords desc, isguess asc, - ST_Distance(point, centroid) * + ST_Distance(feature, centroid) * CASE WHEN rank_address = 16 AND rank_search = 15 THEN 0.2 -- capital city WHEN rank_address = 16 AND rank_search = 16 THEN 0.25 -- city diff --git a/test/bdd/db/import/addressing.feature b/test/bdd/db/import/addressing.feature new file mode 100644 index 00000000..2bff8249 --- /dev/null +++ b/test/bdd/db/import/addressing.feature @@ -0,0 +1,22 @@ +@DB +Feature: Address computation + Tests for filling of place_addressline + + # github #121 + Scenario: Roads crossing boundaries should contain both states + Given the grid + | 1 | | | 2 | | 3 | + | | 7 | | 8 | | | + | 4 | | | 5 | | 6 | + And the named places + | osm | class | type | geometry | + | W1 | highway | road | 7, 8 | + And the named places + | osm | class | type | admin | geometry | + | W10 | boundary | administrative | 5 | (1, 2, 5, 4, 1) | + | W11 | boundary | administrative | 5 | (2, 3, 6, 5, 2) | + When importing + Then place_addressline contains + | object | address | cached_rank_address | + | W1 | W10 | 10 | + | W1 | W11 | 10 | diff --git a/test/bdd/steps/db_ops.py b/test/bdd/steps/db_ops.py index 869cf829..df1d1688 100644 --- a/test/bdd/steps/db_ops.py +++ b/test/bdd/steps/db_ops.py @@ -93,6 +93,12 @@ class NominatimID: self.oid = m.group('id') self.cls = m.group('cls') + def __str__(self): + if self.cls is None: + return self.typ + self.oid + + return '%s%d:%s' % (self.typ, self.oid, self.cls) + def table_select(self): """ Return where clause and parameter list to select the object from a Nominatim table. @@ -109,7 +115,9 @@ class NominatimID: def get_place_id(self, cur): where, params = self.table_select() cur.execute("SELECT place_id FROM placex WHERE %s" % where, params) - eq_(1, cur.rowcount, "Expected exactly 1 entry in placex found %s" % cur.rowcount) + eq_(1, cur.rowcount, + "Expected exactly 1 entry in placex for %s found %s" + % (str(self), cur.rowcount)) return cur.fetchone()[0] @@ -386,6 +394,27 @@ def check_search_name_contents(context): context.db.commit() +@then("place_addressline contains") +def check_place_addressline(context): + cur = context.db.cursor(cursor_factory=psycopg2.extras.DictCursor) + + for row in context.table: + pid = NominatimID(row['object']).get_place_id(cur) + apid = NominatimID(row['address']).get_place_id(cur) + cur.execute(""" SELECT * FROM place_addressline + WHERE place_id = %s AND address_place_id = %s""", + (pid, apid)) + assert_less(0, cur.rowcount, + "No rows found for place %s and address %s" + % (row['object'], row['address'])) + + for res in cur: + for h in row.headings: + if h not in ('address', 'object'): + assert_db_column(res, h, row[h], context) + + context.db.commit() + @then("(?P\w+) expands to(?P no)? interpolation") def check_location_property_osmline(context, oid, neg): cur = context.db.cursor(cursor_factory=psycopg2.extras.DictCursor)