mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-16 15:47:58 +00:00
Compare commits
20 Commits
535ffc1e3f
...
v5.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a13b62fb9 | ||
|
|
3ecda751c4 | ||
|
|
5d4c29b84b | ||
|
|
f1fbc04f33 | ||
|
|
353c985b9f | ||
|
|
2dda9079f0 | ||
|
|
4c91a0bc8d | ||
|
|
31c8ec6db0 | ||
|
|
e2330ff4c1 | ||
|
|
589825d37e | ||
|
|
a93113bc44 | ||
|
|
b042eca382 | ||
|
|
d202a8f7d8 | ||
|
|
af6386bd68 | ||
|
|
862bfdf6fb | ||
|
|
28029edc8b | ||
|
|
d6e9196177 | ||
|
|
e0a750e089 | ||
|
|
93b2a0f194 | ||
|
|
aa3fce6852 |
4
.github/workflows/ci-tests.yml
vendored
4
.github/workflows/ci-tests.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
python: '3.9'
|
||||
- flavour: ubuntu-24
|
||||
ubuntu: 24
|
||||
postgresql: 17
|
||||
postgresql: 18
|
||||
lua: '5.3'
|
||||
dependencies: apt
|
||||
python: 'builtin'
|
||||
@@ -326,7 +326,7 @@ jobs:
|
||||
|
||||
- uses: ./Nominatim/.github/actions/setup-postgresql
|
||||
with:
|
||||
postgresql-version: 17
|
||||
postgresql-version: 18
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
|
||||
36
ChangeLog
36
ChangeLog
@@ -1,3 +1,39 @@
|
||||
5.2.0
|
||||
* increase minimum required Python to 3.9
|
||||
* index and output entrances of buildings and areas (thanks @emlove)
|
||||
* name tags used for creating display names are now configurable
|
||||
(thanks @astridx)
|
||||
* new pattern-replacement query preprocessor (thanks @TuringVerified)
|
||||
* special phrases can now be filtered by presence of tags (thanks @anqixxx)
|
||||
* lua import style now always includes tags required by Nominatim
|
||||
* improved query time reporting and logging
|
||||
* improve word matching for languages with no word boundaries
|
||||
* POIs with addresses inherited from surrounding building are no
|
||||
longer returned in the address layer
|
||||
* avoid creating a directory for the tokenizer when not needed
|
||||
* replace behave with pytest-bdd for BDD testing
|
||||
* refactoring and performance improvements to query parsing
|
||||
* various smaller updates to styles
|
||||
* remove English as default language for South Korea
|
||||
* remove Japanese word variants
|
||||
* updated country names for Norwegians (thanks @Johannes-Andersen)
|
||||
* remove support for deprecated osm2pgsql gazetteer style
|
||||
* fix updating of importances (also needs to update search_name table)
|
||||
* fix query for deletable endpoint to use index again
|
||||
* fix reindexing of contained places when a boundary is deleted and reinstated
|
||||
* fix difference computation error when updating postcodes
|
||||
* bracket handling sanitizer no longer strips bracket terms in the middle of
|
||||
name
|
||||
* reduce precision of stored coordinates to 7-digits everywhere
|
||||
* avoid ST_Relate as it seems buggy on some systems
|
||||
* remove setting for logging queries in DB, no longer functional
|
||||
* postcode updates no longer require a project directory (needed for tests)
|
||||
* refactor locale handling code (thanks @anqixxx)
|
||||
* code updates for newer Python (thanks @emmanuel-ferdman)
|
||||
* better test coverage (thanks @asharmalik19)
|
||||
* various fixes and improvements to documentation
|
||||
(thanks @anqixxx, @dave-meyer, @hasandiwan)
|
||||
|
||||
5.1.0
|
||||
* replace datrie with simple internal trie implementation
|
||||
* add pattern-based postcode parser for queries,
|
||||
|
||||
@@ -9,11 +9,11 @@ versions.
|
||||
|
||||
| Version | End of support for security updates |
|
||||
| ------- | ----------------------------------- |
|
||||
| 5.2.x | 2027-10-29 |
|
||||
| 5.1.x | 2027-04-01 |
|
||||
| 5.0.x | 2027-02-06 |
|
||||
| 4.5.x | 2026-09-12 |
|
||||
| 4.4.x | 2026-03-07 |
|
||||
| 4.3.x | 2025-09-07 |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
@@ -32,8 +32,7 @@ description of the nature and severity of the issue. **
|
||||
Patches for identified security issues are applied to all affected versions and
|
||||
new minor versions are released. At the same time we release a statement at
|
||||
the [Nominatim blog](https://nominatim.org/blog/) describing the nature of the
|
||||
incident. Announcements will also be published at the
|
||||
[geocoding mailinglist](https://lists.openstreetmap.org/listinfo/geocoding).
|
||||
incident.
|
||||
|
||||
## List of Previous Incidents
|
||||
|
||||
|
||||
@@ -17,6 +17,18 @@ breaking changes. **Please read them before running the migration.**
|
||||
and migrate to 4.3 first. Then you can migrate to the current
|
||||
version. It is strongly recommended to do a reimport instead.
|
||||
|
||||
## 5.1.0 -> 5.2.0
|
||||
|
||||
### Lua import style: required extratags removed
|
||||
|
||||
Tags that are required by Nominatim as extratags are now always included
|
||||
independent of what is defined in the style. The line
|
||||
|
||||
flex.add_for_extratags('required')
|
||||
|
||||
is no longer required in custom styles and will throw an error. Simply
|
||||
remove the line from your style.
|
||||
|
||||
## 4.5.0 -> 5.0.0
|
||||
|
||||
### PHP frontend removed
|
||||
|
||||
@@ -49,7 +49,7 @@ Only has an effect for JSON output formats.
|
||||
|
||||
| Parameter | Value | Default |
|
||||
|-----------| ----- | ------- |
|
||||
| addressdetails | 0 or 1 | 0 |
|
||||
| addressdetails | 0 or 1 | 1 |
|
||||
|
||||
When set to 1, include a breakdown of the address into elements.
|
||||
The exact content of the address breakdown depends on the output format.
|
||||
|
||||
@@ -152,7 +152,7 @@ In terms of address details the zoom levels are as follows:
|
||||
|
||||
| Parameter | Value | Default |
|
||||
|-----------| ----- | ------- |
|
||||
| layer | comma-separated list of: `address`, `poi`, `railway`, `natural`, `manmade` | _unset_ (no restriction) |
|
||||
| layer | comma-separated list of: `address`, `poi`, `railway`, `natural`, `manmade` | `address,poi` |
|
||||
|
||||
The layer filter allows to select places by themes.
|
||||
|
||||
@@ -218,7 +218,7 @@ This overrides the specified machine readable format.
|
||||
|
||||
## Examples
|
||||
|
||||
* [https://nominatim.openstreetmap.org/reverse?format=xml&lat=52.5487429714954&lon=-1.81602098644987&zoom=18&addressdetails=1](https://nominatim.openstreetmap.org/reverse?format=xml&lat=52.5487429714954&lon=-1.81602098644987&zoom=18&addressdetails=1)
|
||||
* [https://nominatim.openstreetmap.org/reverse?format=xml&lat=52.5487429714954&lon=-1.81602098644987&zoom=18&addressdetails=1&layer=address](https://nominatim.openstreetmap.org/reverse?format=xml&lat=52.5487429714954&lon=-1.81602098644987&zoom=18&addressdetails=1&layer=address)
|
||||
|
||||
```xml
|
||||
<reversegeocode timestamp="Fri, 06 Nov 09 16:33:54 +0000" querystring="...">
|
||||
@@ -241,7 +241,7 @@ This overrides the specified machine readable format.
|
||||
|
||||
##### Example with `format=jsonv2`
|
||||
|
||||
* [https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=-34.44076&lon=-58.70521](https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=-34.44076&lon=-58.70521)
|
||||
* [https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=-34.44076&lon=-58.70521&layer=address](https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=-34.44076&lon=-58.70521&layer=address)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -273,7 +273,7 @@ This overrides the specified machine readable format.
|
||||
|
||||
##### Example with `format=geojson`
|
||||
|
||||
* [https://nominatim.openstreetmap.org/reverse?format=geojson&lat=44.50155&lon=11.33989](https://nominatim.openstreetmap.org/reverse?format=geojson&lat=44.50155&lon=11.33989)
|
||||
* [https://nominatim.openstreetmap.org/reverse?format=geojson&lat=44.50155&lon=11.33989&layer=address](https://nominatim.openstreetmap.org/reverse?format=geojson&lat=44.50155&lon=11.33989&layer=address)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -325,7 +325,7 @@ This overrides the specified machine readable format.
|
||||
|
||||
##### Example with `format=geocodejson`
|
||||
|
||||
[https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=60.2299&lon=11.1663](https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=60.2299&lon=11.1663)
|
||||
[https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=60.2299&lon=11.1663&layer=address](https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=60.2299&lon=11.1663&layer=address)
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -68,15 +68,16 @@ When Nominatim processes an OSM object, it looks for four kinds of tags:
|
||||
The _main tags_ classify what kind of place the OSM object represents. One
|
||||
OSM object can have more than one main tag. In such case one database entry
|
||||
is created for each main tag. _Name tags_ represent searchable names of the
|
||||
place. _Address tags_ are used to compute the address hierarchy of the place.
|
||||
place. _Address tags_ are used to compute the address information of the place.
|
||||
Address tags are used for searching and for creating a display name of the place.
|
||||
_Extra tags_ are any tags that are not directly related to search but
|
||||
contain interesting additional information.
|
||||
contain interesting additional information. These are just saved in the database
|
||||
and may be returned with the result [on request](../api/Search.md#output-details).
|
||||
|
||||
!!! danger
|
||||
Some tags in the extratags category are used by Nominatim to better
|
||||
classify the place. You want to make sure these are always present
|
||||
in custom styles.
|
||||
classify the place. These tags will always be added, independent of
|
||||
any settings in the style.
|
||||
|
||||
Configuring the style means deciding which key and/or key/value is used
|
||||
in which category.
|
||||
@@ -266,11 +267,7 @@ in turn take precedence over prefix matches.
|
||||
|
||||
##### Presets
|
||||
|
||||
| Name | Description |
|
||||
| :----- | :---------- |
|
||||
| required | Tags that Nominatim will use for various computations when present in extratags. Always include these. |
|
||||
|
||||
In addition, all [presets from ignored tags](#presets_1) are accepted.
|
||||
Accepts all [presets from ignored tags](#presets_1).
|
||||
|
||||
### General pre-filtering
|
||||
|
||||
@@ -426,6 +423,56 @@ is added for extratags.
|
||||
already delete the tiger tags with `set_prefilters()` because that
|
||||
would remove tiger:county before the address tags are processed.
|
||||
|
||||
## Filling additional tables
|
||||
|
||||
Most of the OSM objects are saved in the main `place` table for further
|
||||
processing. In addition to that, there are some smaller tables that save
|
||||
specialised information. The content of these tables can be customized as
|
||||
well.
|
||||
|
||||
### Entrance table
|
||||
|
||||
The table `place_entrance` saves information about OSM nodes that represent
|
||||
an entrance. This data is later mingled with buildings and other areas and
|
||||
can be returned [on request](../api/Search.md#output-details). The table
|
||||
saves the type of entrance as well as a set of custom extra tags.
|
||||
|
||||
The function `set_entrance_filter()` can be used to customize the table's
|
||||
content.
|
||||
|
||||
When called without any parameter, then filling the entrance table will be
|
||||
disabled. When called with a preset name, the appropriate preset will be
|
||||
applied.
|
||||
|
||||
To create a custom configuration, call the function
|
||||
with a table with the following fields:
|
||||
|
||||
* __main_tags__ is a list of tags that mark an entrance node. The value of the
|
||||
first tag found in the list will be used as the entrance type.
|
||||
* __extra_include__ is an optional list of tags to be added to the extratags
|
||||
for this entrance. When left out, all tags except for the ones defined
|
||||
in 'main_tags' will be included. To disable saving of extra tags, set
|
||||
this to the empty list.
|
||||
* __extra_exclude__ defines an optional list of tags to drop before including
|
||||
the remaining tags as extratags. Note that the tags defined in 'main_tags'
|
||||
will always be excluded, independently of this setting.
|
||||
|
||||
To have even more fine-grained control over the output, you can also hand
|
||||
in a callback for processing entrance information. The callback function
|
||||
receives a single parameter, the
|
||||
[osm2pgsql object](https://osm2pgsql.org/doc/manual.html#processing-callbacks).
|
||||
This object itself must not be modified. The callback should return either
|
||||
`nil` when the object is not an entrance. Or it returns a table with a
|
||||
mandatory `entrance` field containing a string with the type of entrance
|
||||
and an optional `extratags` field with a simple key-value table of extra
|
||||
information.
|
||||
|
||||
##### Presets
|
||||
|
||||
| Name | Description |
|
||||
| :----- | :---------- |
|
||||
| default | Standard configuration used with `full` and `extratags` styles. |
|
||||
|
||||
## Customizing osm2pgsql callbacks
|
||||
|
||||
osm2pgsql expects the flex style to implement three callbacks, one process
|
||||
|
||||
@@ -29,7 +29,9 @@ local NAME_FILTER = nil
|
||||
local ADDRESS_TAGS = {}
|
||||
local ADDRESS_FILTER = nil
|
||||
local EXTRATAGS_FILTER
|
||||
local REQUIRED_EXTRATAGS_FILTER
|
||||
local POSTCODE_FALLBACK = true
|
||||
local ENTRANCE_FUNCTION = nil
|
||||
|
||||
-- This file can also be directly require'd instead of running it under
|
||||
-- the themepark framework. In that case the first parameter is usually
|
||||
@@ -40,37 +42,51 @@ if type(themepark) ~= 'table' then
|
||||
themepark = nil
|
||||
end
|
||||
|
||||
-- The single place table.
|
||||
local place_table_definition = {
|
||||
name = "place",
|
||||
ids = { type = 'any', id_column = 'osm_id', type_column = 'osm_type' },
|
||||
columns = {
|
||||
{ column = 'class', type = 'text', not_null = true },
|
||||
{ column = 'type', type = 'text', not_null = true },
|
||||
{ column = 'admin_level', type = 'smallint' },
|
||||
{ column = 'name', type = 'hstore' },
|
||||
{ column = 'address', type = 'hstore' },
|
||||
{ column = 'extratags', type = 'hstore' },
|
||||
{ column = 'geometry', type = 'geometry', projection = 'WGS84', not_null = true },
|
||||
-- The place tables carry the raw OSM information.
|
||||
local table_definitions = {
|
||||
place = {
|
||||
ids = { type = 'any', id_column = 'osm_id', type_column = 'osm_type' },
|
||||
columns = {
|
||||
{ column = 'class', type = 'text', not_null = true },
|
||||
{ column = 'type', type = 'text', not_null = true },
|
||||
{ column = 'admin_level', type = 'smallint' },
|
||||
{ column = 'name', type = 'hstore' },
|
||||
{ column = 'address', type = 'hstore' },
|
||||
{ column = 'extratags', type = 'hstore' },
|
||||
{ column = 'geometry', type = 'geometry', projection = 'WGS84', not_null = true },
|
||||
},
|
||||
indexes = {}
|
||||
},
|
||||
data_tablespace = os.getenv("NOMINATIM_TABLESPACE_PLACE_DATA"),
|
||||
index_tablespace = os.getenv("NOMINATIM_TABLESPACE_PLACE_INDEX"),
|
||||
indexes = {}
|
||||
place_entrance = {
|
||||
ids = { type = 'node', id_column = 'osm_id' },
|
||||
columns = {
|
||||
{ column = 'type', type = 'text', not_null = true },
|
||||
{ column = 'extratags', type = 'hstore' },
|
||||
{ column = 'geometry', type = 'geometry', projection = 'WGS84', not_null = true }
|
||||
},
|
||||
indexes = {}
|
||||
}
|
||||
}
|
||||
|
||||
local insert_row
|
||||
local insert_row = {}
|
||||
local script_path = debug.getinfo(1, "S").source:match("@?(.*/)")
|
||||
local PRESETS = loadfile(script_path .. 'presets.lua')()
|
||||
|
||||
if themepark then
|
||||
themepark:add_table(place_table_definition)
|
||||
insert_row = function(columns)
|
||||
themepark:insert('place', columns, {}, {})
|
||||
end
|
||||
else
|
||||
local place_table = osm2pgsql.define_table(place_table_definition)
|
||||
insert_row = function(columns)
|
||||
place_table:insert(columns)
|
||||
for table_name, table_definition in pairs(table_definitions) do
|
||||
table_definition.name = table_name
|
||||
table_definition.data_tablespace = os.getenv("NOMINATIM_TABLESPACE_PLACE_DATA")
|
||||
table_definition.index_tablespace = os.getenv("NOMINATIM_TABLESPACE_PLACE_INDEX")
|
||||
|
||||
if themepark then
|
||||
themepark:add_table(table_definition)
|
||||
insert_row[table_name] = function(columns)
|
||||
themepark:insert(table_name, columns, {}, {})
|
||||
end
|
||||
else
|
||||
local place_table = osm2pgsql.define_table(table_definition)
|
||||
insert_row[table_name] = function(columns)
|
||||
place_table:insert(columns)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -150,24 +166,6 @@ local function address_fallback(place)
|
||||
return place:clone{names=names}
|
||||
end
|
||||
|
||||
--------- Built-in extratags transformation functions ---------------
|
||||
|
||||
local function default_extratags_filter(p, k)
|
||||
-- Default handling is to copy over place tag for boundaries.
|
||||
-- Nominatim needs this.
|
||||
if k ~= 'boundary' or p.intags.place == nil then
|
||||
return p.extratags
|
||||
end
|
||||
|
||||
local extra = { place = p.intags.place }
|
||||
for kin, vin in pairs(p.extratags) do
|
||||
extra[kin] = vin
|
||||
end
|
||||
|
||||
return extra
|
||||
end
|
||||
EXTRATAGS_FILTER = default_extratags_filter
|
||||
|
||||
----------------- other helper functions -----------------------------
|
||||
|
||||
local function lookup_prefilter_classification(k, v)
|
||||
@@ -429,18 +427,25 @@ function Place:write_row(k, v)
|
||||
return 0
|
||||
end
|
||||
|
||||
local extratags = EXTRATAGS_FILTER(self, k, v)
|
||||
if not (extratags and next(extratags)) then
|
||||
extratags = nil
|
||||
end
|
||||
local extra = EXTRATAGS_FILTER(self, k, v) or {}
|
||||
|
||||
insert_row{
|
||||
for tk, tv in pairs(self.object.tags) do
|
||||
if REQUIRED_EXTRATAGS_FILTER(tk, tv) and extra[tk] == nil then
|
||||
extra[tk] = tv
|
||||
end
|
||||
end
|
||||
|
||||
if extra and next(extra) == nil then
|
||||
extra = nil
|
||||
end
|
||||
|
||||
insert_row.place{
|
||||
class = k,
|
||||
type = v,
|
||||
admin_level = self.admin_level,
|
||||
name = next(self.names) and self.names,
|
||||
address = next(self.address) and self.address,
|
||||
extratags = extratags,
|
||||
extratags = extra,
|
||||
geometry = self.geometry
|
||||
}
|
||||
|
||||
@@ -593,6 +598,16 @@ end
|
||||
|
||||
-- Process functions for all data types
|
||||
function module.process_node(object)
|
||||
if ENTRANCE_FUNCTION ~= nil then
|
||||
local entrance_info = ENTRANCE_FUNCTION(object)
|
||||
if entrance_info ~= nil then
|
||||
insert_row.place_entrance{
|
||||
type = entrance_info.entrance,
|
||||
extratags = entrance_info.extratags,
|
||||
geometry = object:as_point()
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function geom_func(o)
|
||||
return o:as_point()
|
||||
@@ -687,6 +702,15 @@ function module.process_tags(o)
|
||||
end
|
||||
end
|
||||
|
||||
--------- Extratags post-processing functions ---------------
|
||||
|
||||
local function default_extratags_filter(p, k)
|
||||
return p.extratags
|
||||
end
|
||||
|
||||
EXTRATAGS_FILTER = default_extratags_filter
|
||||
REQUIRED_EXTRATAGS_FILTER = module.tag_match(PRESETS.EXTRATAGS)
|
||||
|
||||
--------- Convenience functions for simple style configuration -----------------
|
||||
|
||||
function module.set_prefilters(data)
|
||||
@@ -717,7 +741,7 @@ end
|
||||
function module.add_for_extratags(data)
|
||||
if type(data) == 'string' then
|
||||
local preset = data
|
||||
data = PRESETS.EXTRATAGS[data] or PRESETS.IGNORE_KEYS[data]
|
||||
data = PRESETS.IGNORE_KEYS[data]
|
||||
if data == nil then
|
||||
error('Unknown preset for extratags: ' .. preset)
|
||||
end
|
||||
@@ -917,6 +941,99 @@ function module.set_relation_types(data)
|
||||
end
|
||||
end
|
||||
|
||||
function module.set_entrance_filter(data)
|
||||
if data == nil or type(data) == 'function' then
|
||||
ENTRANCE_FUNCTION = data
|
||||
return nil
|
||||
end
|
||||
|
||||
if type(data) == 'string' then
|
||||
local preset = data
|
||||
data = PRESETS.ENTRANCE_TABLE[data]
|
||||
if data == nil then
|
||||
error('Unknown preset for entrance table: ' .. preset)
|
||||
end
|
||||
end
|
||||
|
||||
ENTRANCE_FUNCTION = nil
|
||||
|
||||
if data.main_tags ~= nil and next(data.main_tags) ~= nil then
|
||||
if data.extra_include ~= nil and next(data.extra_include) == nil then
|
||||
-- shortcut: no extra tags requested
|
||||
ENTRANCE_FUNCTION = function(o)
|
||||
for _, v in ipairs(data.main_tags) do
|
||||
if o.tags[v] ~= nil then
|
||||
return {entrance = o.tags[v]}
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
else
|
||||
if data.extra_include ~= nil then
|
||||
local tags = {}
|
||||
for _, v in pairs(data.extra_include) do
|
||||
tags[v] = true
|
||||
end
|
||||
if data.extra_exclude ~= nil then
|
||||
for _, v in pairs(data.extra_exclude) do
|
||||
tags[v] = nil
|
||||
end
|
||||
end
|
||||
for _, v in pairs(data.main_tags) do
|
||||
tags[v] = nil
|
||||
end
|
||||
|
||||
ENTRANCE_FUNCTION = function(o)
|
||||
for _, v in ipairs(data.main_tags) do
|
||||
if o.tags[v] ~= nil then
|
||||
local entrance = o.tags[v]
|
||||
local extra = {}
|
||||
for k, v in pairs(tags) do
|
||||
extra[k] = o.tags[k]
|
||||
end
|
||||
if next(extra) == nil then
|
||||
extra = nil
|
||||
end
|
||||
return {entrance = entrance, extratags = extra}
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
else
|
||||
local notags = {}
|
||||
if data.extra_exclude ~= nil then
|
||||
for _, v in pairs(data.extra_exclude) do
|
||||
notags[v] = 1
|
||||
end
|
||||
end
|
||||
for _, v in pairs(data.main_tags) do
|
||||
notags[v] = 1
|
||||
end
|
||||
|
||||
ENTRANCE_FUNCTION = function(o)
|
||||
for _, v in ipairs(data.main_tags) do
|
||||
if o.tags[v] ~= nil then
|
||||
local entrance = o.tags[v]
|
||||
local extra = {}
|
||||
for k, v in pairs(o.tags) do
|
||||
if notags[k] ~= 1 then
|
||||
extra[k] = v
|
||||
end
|
||||
end
|
||||
if next(extra) == nil then
|
||||
extra = nil
|
||||
end
|
||||
return {entrance = entrance, extratags = extra}
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function module.get_taginfo()
|
||||
return {main = MAIN_KEYS, name = NAMES, address = ADDRESS_TAGS}
|
||||
|
||||
@@ -172,10 +172,6 @@ module.MAIN_TAGS_POIS = function (group)
|
||||
no = group,
|
||||
yes = group,
|
||||
fire_hydrant = group},
|
||||
entrance = {'always',
|
||||
no = group},
|
||||
["routing:entrance"] = {exclude_when_key_present('entrance'),
|
||||
no = group},
|
||||
healthcare = {'fallback',
|
||||
yes = group,
|
||||
no = group},
|
||||
@@ -204,6 +200,8 @@ module.MAIN_TAGS_POIS = function (group)
|
||||
leisure = {'always',
|
||||
nature_reserve = 'fallback',
|
||||
swimming_pool = 'named',
|
||||
garden = 'named',
|
||||
common = 'named',
|
||||
no = group},
|
||||
lock = {yes = lock_transform},
|
||||
man_made = {pier = 'always',
|
||||
@@ -377,10 +375,15 @@ module.IGNORE_KEYS.address = {'addr:street:*', 'addr:city:*', 'addr:district:*',
|
||||
'addr:province:*', 'addr:subdistrict:*', 'addr:place:*',
|
||||
'addr:TW:dataset'}
|
||||
|
||||
-- Extra tags (prefiltered away)
|
||||
-- INTERNAL: Required extra tags
|
||||
|
||||
module.EXTRATAGS = {}
|
||||
module.EXTRATAGS = {keys = {'wikipedia', 'wikipedia:*', 'wikidata', 'capital'}}
|
||||
|
||||
module.EXTRATAGS.required = {'wikipedia', 'wikipedia:*', 'wikidata', 'capital'}
|
||||
-- Defaults for the entrance table
|
||||
|
||||
module.ENTRANCE_TABLE = {}
|
||||
|
||||
module.ENTRANCE_TABLE.default = {main_tags = {'entrance', 'routing:entrance'},
|
||||
extra_exclude = module.IGNORE_KEYS.metatags}
|
||||
|
||||
return module
|
||||
|
||||
@@ -11,7 +11,6 @@ flex.set_address_tags('core')
|
||||
flex.modify_address_tags('houses')
|
||||
|
||||
flex.ignore_keys('metatags')
|
||||
flex.add_for_extratags('required')
|
||||
|
||||
if cfg.with_extratags then
|
||||
flex.set_unused_handling{delete_keys = {'tiger:*'}}
|
||||
|
||||
@@ -8,7 +8,6 @@ flex.set_address_tags('core')
|
||||
flex.set_postcode_fallback(false)
|
||||
|
||||
flex.ignore_keys('metatags')
|
||||
flex.add_for_extratags('required')
|
||||
|
||||
if cfg.with_extratags then
|
||||
flex.set_unused_handling{delete_keys = {'tiger:*'}}
|
||||
|
||||
@@ -20,7 +20,6 @@ flex.set_address_tags('core')
|
||||
flex.modify_address_tags('houses')
|
||||
|
||||
flex.ignore_keys('metatags')
|
||||
flex.add_for_extratags('required')
|
||||
|
||||
if cfg.with_extratags then
|
||||
flex.set_unused_handling{delete_keys = {'tiger:*'}}
|
||||
@@ -30,3 +29,5 @@ else
|
||||
flex.ignore_keys('name')
|
||||
flex.ignore_keys('address')
|
||||
end
|
||||
|
||||
flex.set_entrance_filter('default')
|
||||
|
||||
@@ -10,7 +10,6 @@ flex.set_address_tags('core')
|
||||
flex.set_postcode_fallback(false)
|
||||
|
||||
flex.ignore_keys('metatags')
|
||||
flex.add_for_extratags('required')
|
||||
|
||||
if cfg.with_extratags then
|
||||
flex.set_unused_handling{delete_keys = {'tiger:*'}}
|
||||
|
||||
@@ -683,11 +683,6 @@ DECLARE
|
||||
BEGIN
|
||||
{% if debug %}RAISE WARNING '% % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type;{% endif %}
|
||||
|
||||
IF NEW.class IN ('routing:entrance', 'entrance') THEN
|
||||
-- We don't need entrance nodes in the placex table.
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
NEW.place_id := nextval('seq_place');
|
||||
NEW.indexed_status := 1; --STATUS_NEW
|
||||
|
||||
|
||||
@@ -634,10 +634,8 @@ DECLARE
|
||||
BEGIN
|
||||
osm_ids := '{}';
|
||||
FOR entrance in SELECT osm_id, type, geometry, extratags
|
||||
FROM place
|
||||
WHERE osm_type = 'N'
|
||||
AND osm_id IN (SELECT unnest(nodes) FROM planet_osm_ways WHERE id=osmid)
|
||||
AND class IN ('routing:entrance', 'entrance')
|
||||
FROM place_entrance
|
||||
WHERE osm_id IN (SELECT unnest(nodes) FROM planet_osm_ways WHERE id=osmid)
|
||||
LOOP
|
||||
osm_ids := array_append(osm_ids, entrance.osm_id);
|
||||
INSERT INTO placex_entrance (place_id, osm_id, type, location, extratags)
|
||||
|
||||
@@ -58,7 +58,10 @@
|
||||
"" : [24, 0]
|
||||
},
|
||||
"leisure" : {
|
||||
"park" : [24, 0]
|
||||
"park" : [24, 0],
|
||||
"nature_reserve" : [24, 0],
|
||||
"garden": [25, 0],
|
||||
"common": [25, 0]
|
||||
},
|
||||
"natural" : {
|
||||
"peak" : [18, 0],
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
#
|
||||
# This file is part of Nominatim. (https://nominatim.org)
|
||||
#
|
||||
# Copyright (C) 2024 by the Nominatim developer community.
|
||||
# Copyright (C) 2025 by the Nominatim developer community.
|
||||
# For a full list of authors see the git log.
|
||||
"""
|
||||
Version information for the Nominatim API.
|
||||
"""
|
||||
|
||||
NOMINATIM_API_VERSION = '5.1.0'
|
||||
NOMINATIM_API_VERSION = '5.2.0'
|
||||
|
||||
@@ -120,26 +120,39 @@ def create_postcode_parent_index(conn: Connection, **_: Any) -> None:
|
||||
|
||||
@_migration(5, 1, 99, 0)
|
||||
def create_placex_entrance_table(conn: Connection, config: Configuration, **_: Any) -> None:
|
||||
""" Add the placex_entrance table to store entrance nodes
|
||||
""" Add the placex_entrance table to store linked-up entrance nodes
|
||||
"""
|
||||
sqlp = SQLPreprocessor(conn, config)
|
||||
sqlp.run_string(conn, """
|
||||
-- Table to store location of entrance nodes
|
||||
DROP TABLE IF EXISTS placex_entrance;
|
||||
CREATE TABLE placex_entrance (
|
||||
place_id BIGINT NOT NULL,
|
||||
osm_id BIGINT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
location GEOMETRY(Point, 4326) NOT NULL,
|
||||
extratags HSTORE
|
||||
);
|
||||
CREATE UNIQUE INDEX idx_placex_entrance_place_id_osm_id ON placex_entrance
|
||||
USING BTREE (place_id, osm_id) {{db.tablespace.search_index}};
|
||||
GRANT SELECT ON placex_entrance TO "{{config.DATABASE_WEBUSER}}" ;
|
||||
if not table_exists(conn, 'placex_entrance'):
|
||||
sqlp = SQLPreprocessor(conn, config)
|
||||
sqlp.run_string(conn, """
|
||||
-- Table to store location of entrance nodes
|
||||
CREATE TABLE placex_entrance (
|
||||
place_id BIGINT NOT NULL,
|
||||
osm_id BIGINT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
location GEOMETRY(Point, 4326) NOT NULL,
|
||||
extratags HSTORE
|
||||
);
|
||||
CREATE UNIQUE INDEX idx_placex_entrance_place_id_osm_id ON placex_entrance
|
||||
USING BTREE (place_id, osm_id) {{db.tablespace.search_index}};
|
||||
GRANT SELECT ON placex_entrance TO "{{config.DATABASE_WEBUSER}}" ;
|
||||
""")
|
||||
|
||||
-- Create an index on the place table for lookups to populate the entrance
|
||||
-- table
|
||||
CREATE INDEX IF NOT EXISTS idx_placex_entrance_lookup ON place
|
||||
USING BTREE (osm_id)
|
||||
WHERE class IN ('routing:entrance', 'entrance');
|
||||
""")
|
||||
|
||||
@_migration(5, 1, 99, 1)
|
||||
def create_place_entrance_table(conn: Connection, config: Configuration, **_: Any) -> None:
|
||||
""" Add the place_entrance table to store incomming entrance nodes
|
||||
"""
|
||||
if not table_exists(conn, 'place_entrance'):
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
-- Table to store location of entrance nodes
|
||||
CREATE TABLE place_entrance (
|
||||
osm_id BIGINT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
extratags HSTORE,
|
||||
geometry GEOMETRY(Point, 4326) NOT NULL
|
||||
);
|
||||
CREATE UNIQUE INDEX place_entrance_osm_id_idx ON place_entrance
|
||||
USING BTREE (osm_id);
|
||||
""")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# This file is part of Nominatim. (https://nominatim.org)
|
||||
#
|
||||
# Copyright (C) 2024 by the Nominatim developer community.
|
||||
# Copyright (C) 2025 by the Nominatim developer community.
|
||||
# For a full list of authors see the git log.
|
||||
"""
|
||||
Version information for Nominatim.
|
||||
@@ -55,7 +55,7 @@ def parse_version(version: str) -> NominatimVersion:
|
||||
return NominatimVersion(*[int(x) for x in parts[:2] + parts[2].split('-')])
|
||||
|
||||
|
||||
NOMINATIM_VERSION = parse_version('5.1.99-0')
|
||||
NOMINATIM_VERSION = parse_version('5.2.0-0')
|
||||
|
||||
POSTGRESQL_REQUIRED_VERSION = (12, 0)
|
||||
POSTGIS_REQUIRED_VERSION = (3, 0)
|
||||
|
||||
@@ -8,8 +8,10 @@ Feature: Entrance nodes are recorded
|
||||
Given the places
|
||||
| osm | class | type | geometry | extratags |
|
||||
| W1 | building | yes | (1,2,3,4,1) | |
|
||||
| N1 | entrance | main | 1 | 'wheelchair': 'yes' |
|
||||
| N2 | entrance | yes | 3 | |
|
||||
And the entrances
|
||||
| osm | type | geometry | extratags |
|
||||
| N1 | main | 1 | 'wheelchair': 'yes' |
|
||||
| N2 | yes | 3 | |
|
||||
And the ways
|
||||
| id | nodes |
|
||||
| 1 | 1,2,3,4,1 |
|
||||
|
||||
@@ -18,7 +18,7 @@ Feature: Querying fo postcode variants
|
||||
| 10 | | | | 11 |
|
||||
And the places
|
||||
| osm | class | type | name | addr+postcode | geometry |
|
||||
| W1 | highway | path | De Weide | 3993 DX | 10,11 |
|
||||
| W1 | highway | path | De Weide | <postcode> | 10,11 |
|
||||
When importing
|
||||
When geocoding "3993 DX"
|
||||
Then result 0 contains
|
||||
|
||||
@@ -17,10 +17,12 @@ Feature: Entrance nodes are recorded
|
||||
| W1 | 1 |
|
||||
Then placex_entrance contains exactly
|
||||
| place_id | osm_id | type | location!wkt | extratags |
|
||||
When updating places
|
||||
| osm | class | type | geometry |
|
||||
| N1 | entrance | main | 1 |
|
||||
| W1 | building | yes | (1,2,3,4,1) |
|
||||
When updating entrances
|
||||
| osm | type | geometry |
|
||||
| N1 | main | 1 |
|
||||
And updating places
|
||||
| osm | class | type | geometry |
|
||||
| W1 | building | yes | (1,2,3,4,1) |
|
||||
Then placex contains exactly
|
||||
| object | place_id |
|
||||
| W1 | 1 |
|
||||
@@ -46,13 +48,15 @@ Feature: Entrance nodes are recorded
|
||||
| W1 | 2 |
|
||||
Then placex_entrance contains exactly
|
||||
| place_id | osm_id | type | location!wkt | extratags |
|
||||
When updating places
|
||||
When marking for delete N1
|
||||
And updating entrances
|
||||
| osm | type | geometry |
|
||||
| N1 | main | 1 |
|
||||
And updating places
|
||||
| osm | class | type | geometry |
|
||||
| N1 | entrance | main | 1 |
|
||||
| W1 | building | yes | (1,2,3,4,1) |
|
||||
Then placex contains exactly
|
||||
| object | place_id |
|
||||
| N1 | 1 |
|
||||
| W1 | 2 |
|
||||
And placex_entrance contains exactly
|
||||
| place_id | osm_id | type | location!wkt | extratags |
|
||||
@@ -64,8 +68,10 @@ Feature: Entrance nodes are recorded
|
||||
| 4 | 3 |
|
||||
Given the places
|
||||
| osm | class | type | geometry |
|
||||
| N1 | entrance | main | 1 |
|
||||
| W1 | building | yes | (1,2,3,4,1) |
|
||||
And the entrances
|
||||
| osm | type | geometry |
|
||||
| N1 | main | 1 |
|
||||
And the ways
|
||||
| id | nodes |
|
||||
| 1 | 1, 2, 3, 4, 1 |
|
||||
@@ -79,7 +85,7 @@ Feature: Entrance nodes are recorded
|
||||
When marking for delete N1
|
||||
And updating places
|
||||
| osm | class | type | geometry |
|
||||
| W1 | building | yes | (2,3,4,2) |
|
||||
| W1 | building | yes | (1,2,3,4,1) |
|
||||
Then placex contains exactly
|
||||
| object | place_id |
|
||||
| W1 | 1 |
|
||||
@@ -92,9 +98,11 @@ Feature: Entrance nodes are recorded
|
||||
| 4 | 3 |
|
||||
Given the places
|
||||
| osm | class | type | geometry |
|
||||
| N1 | entrance | main | 1 |
|
||||
| N3 | entrance | yes | 3 |
|
||||
| W1 | building | yes | (1,2,3,4,1) |
|
||||
Given the entrances
|
||||
| osm | type | geometry |
|
||||
| N1 | main | 1 |
|
||||
| N3 | yes | 3 |
|
||||
And the ways
|
||||
| id | nodes |
|
||||
| 1 | 1, 2, 3, 4, 1 |
|
||||
@@ -109,7 +117,7 @@ Feature: Entrance nodes are recorded
|
||||
When marking for delete N1
|
||||
And updating places
|
||||
| osm | class | type | geometry |
|
||||
| W1 | building | yes | (2,3,4,2) |
|
||||
| W1 | building | yes | (1,2,3,4,1) |
|
||||
Then placex contains exactly
|
||||
| object | place_id |
|
||||
| W1 | 1 |
|
||||
|
||||
124
test/bdd/features/osm2pgsql/import/entrances.feature
Normal file
124
test/bdd/features/osm2pgsql/import/entrances.feature
Normal file
@@ -0,0 +1,124 @@
|
||||
Feature: Import of entrance objects by osm2pgsql
|
||||
Testing of correct setup of the entrance table
|
||||
|
||||
Scenario: Import simple entrance
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tshop=sweets,entrance=yes,access=public x4.5 y-4
|
||||
n2 Trouting:entrance=main x66.1 y0.1
|
||||
n3 Tentrance=main,routing:entrance=foot x1 y2
|
||||
n4 Thighway=bus_stop
|
||||
"""
|
||||
Then place contains exactly
|
||||
| object | class | type |
|
||||
| N1 | shop | sweets |
|
||||
| N4 | highway | bus_stop |
|
||||
And place_entrance contains exactly
|
||||
| osm_id | type | extratags!dict | geometry!wkt |
|
||||
| 1 | yes | 'shop': 'sweets', 'access': 'public' | 4.5 -4 |
|
||||
| 2 | main | - | 66.1 0.1 |
|
||||
| 3 | main | - | 1 2 |
|
||||
|
||||
Scenario: Addresses and entrance information can exist on the same node
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Taddr:housenumber=10,addr:street=North,entrance=main
|
||||
"""
|
||||
Then place contains exactly
|
||||
| object | class | type | address+housenumber |
|
||||
| N1 | place | house | 10 |
|
||||
And place_entrance contains exactly
|
||||
| osm_id | type |
|
||||
| 1 | main |
|
||||
Scenario Outline: Entrance import can be disabled
|
||||
Given the lua style file
|
||||
"""
|
||||
local flex = require('import-full')
|
||||
flex.set_entrance_filter<param>
|
||||
"""
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tentrance=yes,access=public
|
||||
n2 Trouting:entrance=main
|
||||
"""
|
||||
Then place contains exactly
|
||||
| object |
|
||||
And place_entrance contains exactly
|
||||
| osm_id |
|
||||
|
||||
Examples:
|
||||
| param |
|
||||
| () |
|
||||
| (nil) |
|
||||
| {} |
|
||||
| {include={'access'}} |
|
||||
| {main_tags={}} |
|
||||
|
||||
Scenario: Entrance import can have custom main tags
|
||||
Given the lua style file
|
||||
"""
|
||||
local flex = require('import-full')
|
||||
flex.set_entrance_filter{main_tags = {'door'}}
|
||||
"""
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tentrance=yes,access=public
|
||||
n2 Tdoor=foot,entrance=yes
|
||||
"""
|
||||
Then place contains exactly
|
||||
| object |
|
||||
And place_entrance contains exactly
|
||||
| osm_id | type | extratags!dict |
|
||||
| 2 | foot | 'entrance': 'yes' |
|
||||
|
||||
Scenario: Entrance import can have custom extra tags included
|
||||
Given the lua style file
|
||||
"""
|
||||
local flex = require('import-full')
|
||||
flex.set_entrance_filter{main_tags = {'entrance'},
|
||||
extra_include = {'access'}}
|
||||
"""
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tentrance=yes,access=public,shop=newspaper
|
||||
n2 Tentrance=yes,shop=sweets
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type | extratags!dict |
|
||||
| 1 | yes | 'access': 'public' |
|
||||
| 2 | yes | - |
|
||||
|
||||
Scenario: Entrance import can have custom extra tags excluded
|
||||
Given the lua style file
|
||||
"""
|
||||
local flex = require('import-full')
|
||||
flex.set_entrance_filter{main_tags = {'entrance', 'door'},
|
||||
extra_exclude = {'shop'}}
|
||||
"""
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tentrance=yes,access=public,shop=newspaper
|
||||
n2 Tentrance=yes,door=yes,shop=sweets
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type | extratags!dict |
|
||||
| 1 | yes | 'access': 'public' |
|
||||
| 2 | yes | - |
|
||||
|
||||
Scenario: Entrance import can have a custom function
|
||||
Given the lua style file
|
||||
"""
|
||||
local flex = require('import-full')
|
||||
flex.set_entrance_filter(function(object)
|
||||
return {entrance='always', extratags = {ref = '1'}}
|
||||
end)
|
||||
"""
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tentrance=yes,access=public,shop=newspaper
|
||||
n2 Tshop=sweets
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type | extratags!dict |
|
||||
| 1 | always | 'ref': '1' |
|
||||
| 2 | always | 'ref': '1' |
|
||||
@@ -40,3 +40,26 @@ Feature: Import of simple objects by osm2pgsql
|
||||
Then place contains exactly
|
||||
| object | class | type |
|
||||
| N1 | place | house |
|
||||
|
||||
Scenario Outline: Tags used by Nominatim internally are always imported
|
||||
Given the lua style file
|
||||
"""
|
||||
local flex = require('import-<style>')
|
||||
"""
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tboundary=administrative,place=city,name=Foo,wikipedia:de=Foo
|
||||
n2 Tplace=hamlet,wikidata=Q1234321,name=Bar
|
||||
"""
|
||||
Then place contains exactly
|
||||
| object | class | extratags!dict |
|
||||
| N1 | boundary | 'place': 'city', 'wikipedia:de': 'Foo' |
|
||||
| N2 | place | 'wikidata': 'Q1234321' |
|
||||
|
||||
Examples:
|
||||
| style |
|
||||
| admin |
|
||||
| street |
|
||||
| address |
|
||||
| full |
|
||||
| extratags |
|
||||
|
||||
106
test/bdd/features/osm2pgsql/update/entrances.feature
Normal file
106
test/bdd/features/osm2pgsql/update/entrances.feature
Normal file
@@ -0,0 +1,106 @@
|
||||
Feature: Update of entrance objects by osm2pgsql
|
||||
Testing of correct update of the entrance table
|
||||
|
||||
Scenario: A new entrance is added
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tshop=shoes
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id |
|
||||
When updating osm data
|
||||
"""
|
||||
n2 Tentrance=yes
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type |
|
||||
| 2 | yes |
|
||||
|
||||
Scenario: An existing entrance is deleted
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tentrance=yes
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type |
|
||||
| 1 | yes |
|
||||
When updating osm data
|
||||
"""
|
||||
n1 dD
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id |
|
||||
|
||||
Scenario: An existing node becomes an entrance
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tshop=sweets
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type |
|
||||
And place contains exactly
|
||||
| object | class |
|
||||
| N1 | shop |
|
||||
When updating osm data
|
||||
"""
|
||||
n1 Tshop=sweets,entrance=yes
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type |
|
||||
| 1 | yes |
|
||||
And place contains exactly
|
||||
| object | class |
|
||||
| N1 | shop |
|
||||
|
||||
Scenario: An existing entrance tag is removed
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tshop=sweets,entrance=yes
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type |
|
||||
| 1 | yes |
|
||||
And place contains exactly
|
||||
| object | class |
|
||||
| N1 | shop |
|
||||
When updating osm data
|
||||
"""
|
||||
n1 Tshop=sweets
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type |
|
||||
And place contains exactly
|
||||
| object | class |
|
||||
| N1 | shop |
|
||||
|
||||
Scenario: Extratags are added to an entrance
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tentrance=yes
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type | extratags |
|
||||
| 1 | yes | - |
|
||||
When updating osm data
|
||||
"""
|
||||
n1 Tentrance=yes,access=yes
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type | extratags!dict |
|
||||
| 1 | yes | 'access': 'yes' |
|
||||
|
||||
Scenario: Extratags are deleted from an entrance
|
||||
When loading osm data
|
||||
"""
|
||||
n1 Tentrance=yes,access=yes
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type | extratags!dict |
|
||||
| 1 | yes | 'access': 'yes' |
|
||||
When updating osm data
|
||||
"""
|
||||
n1 Tentrance=yes
|
||||
"""
|
||||
Then place_entrance contains exactly
|
||||
| osm_id | type | extratags |
|
||||
| 1 | yes | - |
|
||||
@@ -82,6 +82,21 @@ def import_places(db_conn, named, datatable, node_grid):
|
||||
PlaceColumn(node_grid).add_row(datatable[0], row, named is not None).db_insert(cur)
|
||||
|
||||
|
||||
@given(step_parse('the entrances'), target_fixture=None)
|
||||
def import_place_entrances(db_conn, datatable, node_grid):
|
||||
""" Insert todo rows into the place_entrance table.
|
||||
"""
|
||||
with db_conn.cursor() as cur:
|
||||
for row in datatable[1:]:
|
||||
data = PlaceColumn(node_grid).add_row(datatable[0], row, False)
|
||||
assert data.columns['osm_type'] == 'N'
|
||||
|
||||
cur.execute("""INSERT INTO place_entrance (osm_id, type, extratags, geometry)
|
||||
VALUES (%s, %s, %s, {})""".format(data.get_wkt()),
|
||||
(data.columns['osm_id'], data.columns['type'],
|
||||
data.columns.get('extratags')))
|
||||
|
||||
|
||||
@given('the ways', target_fixture=None)
|
||||
def import_ways(db_conn, datatable):
|
||||
""" Import raw ways into the osm2pgsql way middle table.
|
||||
@@ -151,6 +166,23 @@ def do_update(db_conn, update_config, node_grid, datatable):
|
||||
return _collect_place_ids(db_conn)
|
||||
|
||||
|
||||
@when('updating entrances', target_fixture=None)
|
||||
def update_place_entrances(db_conn, datatable, node_grid):
|
||||
""" Insert todo rows into the place_entrance table.
|
||||
"""
|
||||
with db_conn.cursor() as cur:
|
||||
for row in datatable[1:]:
|
||||
data = PlaceColumn(node_grid).add_row(datatable[0], row, False)
|
||||
assert data.columns['osm_type'] == 'N'
|
||||
|
||||
cur.execute("DELETE FROM place_entrance WHERE osm_id = %s",
|
||||
(data.columns['osm_id'],))
|
||||
cur.execute("""INSERT INTO place_entrance (osm_id, type, extratags, geometry)
|
||||
VALUES (%s, %s, %s, {})""".format(data.get_wkt()),
|
||||
(data.columns['osm_id'], data.columns['type'],
|
||||
data.columns.get('extratags')))
|
||||
|
||||
|
||||
@when('updating postcodes')
|
||||
def do_postcode_update(update_config):
|
||||
""" Recompute the postcode centroids.
|
||||
@@ -168,6 +200,9 @@ def do_delete_place(db_conn, update_config, node_grid, otype, oid):
|
||||
cur.execute('DELETE FROM place WHERE osm_type = %s and osm_id = %s',
|
||||
(otype, oid))
|
||||
cur.execute('SELECT flush_deleted_places()')
|
||||
if otype == 'N':
|
||||
cur.execute('DELETE FROM place_entrance WHERE osm_id = %s',
|
||||
(oid, ))
|
||||
db_conn.commit()
|
||||
|
||||
cli.nominatim(['index', '-q'], update_config.environ)
|
||||
|
||||
@@ -118,6 +118,17 @@ class PlaceColumn:
|
||||
else:
|
||||
self.columns[column] = {key: value}
|
||||
|
||||
def get_wkt(self):
|
||||
if self.columns['osm_type'] == 'N' and self.geometry is None:
|
||||
pt = self.grid.get(str(self.columns['osm_id'])) if self.grid else None
|
||||
if pt is None:
|
||||
pt = (random.uniform(-180, 180), random.uniform(-90, 90))
|
||||
|
||||
return "ST_SetSRID(ST_Point({}, {}), 4326)".format(*pt)
|
||||
|
||||
assert self.geometry is not None, "Geometry missing"
|
||||
return self.geometry
|
||||
|
||||
def db_delete(self, cursor):
|
||||
""" Issue a delete for the given OSM object.
|
||||
"""
|
||||
@@ -127,17 +138,8 @@ class PlaceColumn:
|
||||
def db_insert(self, cursor):
|
||||
""" Insert the collected data into the database.
|
||||
"""
|
||||
if self.columns['osm_type'] == 'N' and self.geometry is None:
|
||||
pt = self.grid.get(str(self.columns['osm_id'])) if self.grid else None
|
||||
if pt is None:
|
||||
pt = (random.uniform(-180, 180), random.uniform(-90, 90))
|
||||
|
||||
self.geometry = "ST_SetSRID(ST_Point({}, {}), 4326)".format(*pt)
|
||||
else:
|
||||
assert self.geometry is not None, "Geometry missing"
|
||||
|
||||
query = 'INSERT INTO place ({}, geometry) values({}, {})'.format(
|
||||
','.join(self.columns.keys()),
|
||||
','.join(['%s' for x in range(len(self.columns))]),
|
||||
self.geometry)
|
||||
self.get_wkt())
|
||||
cursor.execute(query, list(self.columns.values()))
|
||||
|
||||
Reference in New Issue
Block a user