forked from hans/Nominatim
use information from tokenizer to determine street vs. place address
So far the SQL logic used the information from the address field to determine if an address is attached to a street or place. This changes the logic to use the information provided in the token_info. This allows sanitizers to enforce a certain parenting without changing the visible address information.
This commit is contained in:
@@ -189,6 +189,28 @@ a house number token text. If a place has multiple house numbers they must
|
|||||||
be listed with a semicolon as delimiter. Must be NULL when the place has no
|
be listed with a semicolon as delimiter. Must be NULL when the place has no
|
||||||
house numbers.
|
house numbers.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
FUNCTION token_is_street_address(info JSONB) RETURNS BOOLEAN
|
||||||
|
```
|
||||||
|
|
||||||
|
Return true if this is an object that should be parented against a street.
|
||||||
|
Only relevant for objects with address rank 30.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
FUNCTION token_has_addr_street(info JSONB) RETURNS BOOLEAN
|
||||||
|
```
|
||||||
|
|
||||||
|
Return true if there are street names to match against for finding the
|
||||||
|
parent of the object.
|
||||||
|
|
||||||
|
|
||||||
|
```sql
|
||||||
|
FUNCTION token_has_addr_place(info JSONB) RETURNS BOOLEAN
|
||||||
|
```
|
||||||
|
|
||||||
|
Return true if there are place names to match against for finding the
|
||||||
|
parent of the object.
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
FUNCTION token_matches_street(info JSONB, street_tokens INTEGER[]) RETURNS BOOLEAN
|
FUNCTION token_matches_street(info JSONB, street_tokens INTEGER[]) RETURNS BOOLEAN
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -996,7 +996,7 @@ BEGIN
|
|||||||
|
|
||||||
{% if debug %}RAISE WARNING 'finding street for % %', NEW.osm_type, NEW.osm_id;{% endif %}
|
{% if debug %}RAISE WARNING 'finding street for % %', NEW.osm_type, NEW.osm_id;{% endif %}
|
||||||
NEW.parent_place_id := null;
|
NEW.parent_place_id := null;
|
||||||
is_place_address := coalesce(not NEW.address ? 'street' and NEW.address ? 'place', FALSE);
|
is_place_address := not token_is_street_address(NEW.token_info);
|
||||||
|
|
||||||
-- We have to find our parent road.
|
-- We have to find our parent road.
|
||||||
NEW.parent_place_id := find_parent_for_poi(NEW.osm_type, NEW.osm_id,
|
NEW.parent_place_id := find_parent_for_poi(NEW.osm_type, NEW.osm_id,
|
||||||
@@ -1013,7 +1013,7 @@ BEGIN
|
|||||||
SELECT p.country_code, p.postcode, p.name FROM placex p
|
SELECT p.country_code, p.postcode, p.name FROM placex p
|
||||||
WHERE p.place_id = NEW.parent_place_id INTO location;
|
WHERE p.place_id = NEW.parent_place_id INTO location;
|
||||||
|
|
||||||
IF is_place_address THEN
|
IF is_place_address and NEW.address ? 'place' THEN
|
||||||
-- Check if the addr:place tag is part of the parent name
|
-- Check if the addr:place tag is part of the parent name
|
||||||
SELECT count(*) INTO i
|
SELECT count(*) INTO i
|
||||||
FROM svals(location.name) AS pname WHERE pname = NEW.address->'place';
|
FROM svals(location.name) AS pname WHERE pname = NEW.address->'place';
|
||||||
|
|||||||
@@ -41,10 +41,17 @@ AS $$
|
|||||||
$$ LANGUAGE SQL IMMUTABLE STRICT;
|
$$ LANGUAGE SQL IMMUTABLE STRICT;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION token_is_street_address(info JSONB)
|
||||||
|
RETURNS BOOLEAN
|
||||||
|
AS $$
|
||||||
|
SELECT info->>'street' is not null or info->>'place' is null;
|
||||||
|
$$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION token_has_addr_street(info JSONB)
|
CREATE OR REPLACE FUNCTION token_has_addr_street(info JSONB)
|
||||||
RETURNS BOOLEAN
|
RETURNS BOOLEAN
|
||||||
AS $$
|
AS $$
|
||||||
SELECT info->>'street' is not null;
|
SELECT info->>'street' is not null and info->>'street' != '{}';
|
||||||
$$ LANGUAGE SQL IMMUTABLE;
|
$$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,13 @@ AS $$
|
|||||||
$$ LANGUAGE SQL IMMUTABLE STRICT;
|
$$ LANGUAGE SQL IMMUTABLE STRICT;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION token_is_street_address(info JSONB)
|
||||||
|
RETURNS BOOLEAN
|
||||||
|
AS $$
|
||||||
|
SELECT info->>'street' is not null or info->>'place' is null;
|
||||||
|
$$ LANGUAGE SQL IMMUTABLE;
|
||||||
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION token_has_addr_street(info JSONB)
|
CREATE OR REPLACE FUNCTION token_has_addr_street(info JSONB)
|
||||||
RETURNS BOOLEAN
|
RETURNS BOOLEAN
|
||||||
AS $$
|
AS $$
|
||||||
|
|||||||
@@ -720,7 +720,7 @@ class _TokenInfo:
|
|||||||
self.names: Optional[str] = None
|
self.names: Optional[str] = None
|
||||||
self.housenumbers: Set[str] = set()
|
self.housenumbers: Set[str] = set()
|
||||||
self.housenumber_tokens: Set[int] = set()
|
self.housenumber_tokens: Set[int] = set()
|
||||||
self.street_tokens: Set[int] = set()
|
self.street_tokens: Optional[Set[int]] = None
|
||||||
self.place_tokens: Set[int] = set()
|
self.place_tokens: Set[int] = set()
|
||||||
self.address_tokens: Dict[str, str] = {}
|
self.address_tokens: Dict[str, str] = {}
|
||||||
self.postcode: Optional[str] = None
|
self.postcode: Optional[str] = None
|
||||||
@@ -742,7 +742,7 @@ class _TokenInfo:
|
|||||||
out['hnr'] = ';'.join(self.housenumbers)
|
out['hnr'] = ';'.join(self.housenumbers)
|
||||||
out['hnr_tokens'] = self._mk_array(self.housenumber_tokens)
|
out['hnr_tokens'] = self._mk_array(self.housenumber_tokens)
|
||||||
|
|
||||||
if self.street_tokens:
|
if self.street_tokens is not None:
|
||||||
out['street'] = self._mk_array(self.street_tokens)
|
out['street'] = self._mk_array(self.street_tokens)
|
||||||
|
|
||||||
if self.place_tokens:
|
if self.place_tokens:
|
||||||
@@ -776,6 +776,8 @@ class _TokenInfo:
|
|||||||
def add_street(self, tokens: Iterable[int]) -> None:
|
def add_street(self, tokens: Iterable[int]) -> None:
|
||||||
""" Add addr:street match terms.
|
""" Add addr:street match terms.
|
||||||
"""
|
"""
|
||||||
|
if self.street_tokens is None:
|
||||||
|
self.street_tokens = set()
|
||||||
self.street_tokens.update(tokens)
|
self.street_tokens.update(tokens)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -523,7 +523,7 @@ class TestPlaceAddress:
|
|||||||
def test_process_place_nonexisting_street(self):
|
def test_process_place_nonexisting_street(self):
|
||||||
info = self.process_address(street='Grand Road')
|
info = self.process_address(street='Grand Road')
|
||||||
|
|
||||||
assert 'street' not in info
|
assert info['street'] == '{}'
|
||||||
|
|
||||||
|
|
||||||
def test_process_place_multiple_street_tags(self):
|
def test_process_place_multiple_street_tags(self):
|
||||||
@@ -538,7 +538,7 @@ class TestPlaceAddress:
|
|||||||
def test_process_place_street_empty(self):
|
def test_process_place_street_empty(self):
|
||||||
info = self.process_address(street='🜵')
|
info = self.process_address(street='🜵')
|
||||||
|
|
||||||
assert 'street' not in info
|
assert info['street'] == '{}'
|
||||||
|
|
||||||
|
|
||||||
def test_process_place_street_from_cache(self):
|
def test_process_place_street_from_cache(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user