mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-14 10:27:57 +00:00
Compare commits
28 Commits
docs-3.7.x
...
v3.7.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b51efd876f | ||
|
|
405279dae3 | ||
|
|
3dd223dfa3 | ||
|
|
7e6125ada5 | ||
|
|
93b72e4e9b | ||
|
|
3bf57e6d2a | ||
|
|
e9ce5714a7 | ||
|
|
ff1a49a0f8 | ||
|
|
ec2873fbf6 | ||
|
|
5dee3cf7f7 | ||
|
|
341cb55690 | ||
|
|
055b5a46ba | ||
|
|
6e8d4c0dac | ||
|
|
baf684195b | ||
|
|
b0832669a3 | ||
|
|
243394b1c2 | ||
|
|
0f14851c98 | ||
|
|
b15a687564 | ||
|
|
0289d125da | ||
|
|
76ee6959c1 | ||
|
|
74c74dde07 | ||
|
|
f7e4bfa980 | ||
|
|
4a6e9ba187 | ||
|
|
10d99893f9 | ||
|
|
b7a5a8b5f7 | ||
|
|
6ed495bfc2 | ||
|
|
cd7c841f5b | ||
|
|
8f9c10c762 |
2
.github/actions/build-nominatim/action.yml
vendored
2
.github/actions/build-nominatim/action.yml
vendored
@@ -6,7 +6,7 @@ runs:
|
||||
steps:
|
||||
- name: Install prerequisites
|
||||
run: |
|
||||
sudo apt-get install -y -qq libboost-system-dev libboost-filesystem-dev libexpat1-dev zlib1g-dev libbz2-dev libpq-dev libproj-dev libicu-dev python3-psycopg2 python3-pyosmium python3-dotenv python3-psutil python3-jinja2 python3-icu python3-argparse-manpage
|
||||
sudo apt-get install -y -qq libboost-system-dev libboost-filesystem-dev libexpat1-dev zlib1g-dev libbz2-dev libpq-dev libproj-dev libicu-dev python3-psycopg2 python3-pyosmium python3-dotenv python3-psutil python3-jinja2 python3-icu
|
||||
shell: bash
|
||||
|
||||
- name: Download dependencies
|
||||
|
||||
4
.github/actions/setup-postgresql/action.yml
vendored
4
.github/actions/setup-postgresql/action.yml
vendored
@@ -14,8 +14,10 @@ runs:
|
||||
steps:
|
||||
- name: Remove existing PostgreSQL
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get purge -yq postgresql*
|
||||
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
||||
sudo apt-get update -qq
|
||||
|
||||
shell: bash
|
||||
|
||||
- name: Install PostgreSQL
|
||||
|
||||
41
.github/workflows/ci-tests.yml
vendored
41
.github/workflows/ci-tests.yml
vendored
@@ -69,7 +69,18 @@ jobs:
|
||||
working-directory: Nominatim/test/bdd
|
||||
|
||||
import:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
ubuntu: [18, 20]
|
||||
include:
|
||||
- ubuntu: 18
|
||||
postgresql: 9.5
|
||||
postgis: 2.5
|
||||
- ubuntu: 20
|
||||
postgresql: 13
|
||||
postgis: 3
|
||||
|
||||
runs-on: ubuntu-${{ matrix.ubuntu }}.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -95,12 +106,24 @@ jobs:
|
||||
monaco-latest.osm.pbf
|
||||
key: nominatim-test-data-${{ steps.get-date.outputs.date }}
|
||||
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.5
|
||||
if: matrix.ubuntu == 18
|
||||
|
||||
- uses: ./Nominatim/.github/actions/setup-postgresql
|
||||
with:
|
||||
postgresql-version: 13
|
||||
postgis-version: 3
|
||||
postgresql-version: ${{ matrix.postgresql }}
|
||||
postgis-version: ${{ matrix.postgis }}
|
||||
- uses: ./Nominatim/.github/actions/build-nominatim
|
||||
|
||||
- name: Install extra dependencies for Ubuntu 18
|
||||
run: |
|
||||
sudo apt-get install libicu-dev
|
||||
pip3 install python-dotenv psycopg2==2.7.7 jinja2==2.8 psutil==5.4.2 pyicu osmium
|
||||
shell: bash
|
||||
if: matrix.ubuntu == 18
|
||||
|
||||
- name: Clean installation
|
||||
run: rm -rf Nominatim build
|
||||
shell: bash
|
||||
@@ -123,10 +146,14 @@ jobs:
|
||||
run: nominatim special-phrases --import-from-wiki
|
||||
working-directory: data-env
|
||||
|
||||
- name: Check import
|
||||
- name: Check full import
|
||||
run: nominatim admin --check-database
|
||||
working-directory: data-env
|
||||
|
||||
- name: Warm up database
|
||||
run: nominatim admin --warm
|
||||
working-directory: data-env
|
||||
|
||||
- name: Run update
|
||||
run: |
|
||||
nominatim replication --init
|
||||
@@ -134,7 +161,11 @@ jobs:
|
||||
working-directory: data-env
|
||||
|
||||
- name: Run reverse-only import
|
||||
run : nominatim import --osm-file ../monaco-latest.osm.pbf --reverse-only
|
||||
run : nominatim import --osm-file ../monaco-latest.osm.pbf --reverse-only --no-updates
|
||||
working-directory: data-env
|
||||
env:
|
||||
NOMINATIM_DATABASE_DSN: pgsql:dbname=reverse
|
||||
|
||||
- name: Check reverse import
|
||||
run: nominatim admin --check-database
|
||||
working-directory: data-env
|
||||
|
||||
@@ -20,7 +20,7 @@ project(nominatim)
|
||||
|
||||
set(NOMINATIM_VERSION_MAJOR 3)
|
||||
set(NOMINATIM_VERSION_MINOR 7)
|
||||
set(NOMINATIM_VERSION_PATCH 0)
|
||||
set(NOMINATIM_VERSION_PATCH 2)
|
||||
|
||||
set(NOMINATIM_VERSION "${NOMINATIM_VERSION_MAJOR}.${NOMINATIM_VERSION_MINOR}.${NOMINATIM_VERSION_PATCH}")
|
||||
|
||||
|
||||
16
ChangeLog
16
ChangeLog
@@ -1,3 +1,19 @@
|
||||
3.7.2
|
||||
|
||||
* fix database check for reverse-only imports
|
||||
* do not error out in status API result when import date is missing
|
||||
* add array_key_last function for PHP < 7.3 (thanks to @woodpack)
|
||||
* fix more url when server name is unknown (thanks to @mogita)
|
||||
* commit changes to replication log table
|
||||
|
||||
3.7.1
|
||||
|
||||
* fix smaller issues with special phrases import
|
||||
* add index to speed up continued indexing during import
|
||||
* fix index on location_property_tiger(parent_place_id)
|
||||
* make sure Python code is backward-compatible with Python 3.5
|
||||
* various documentation fixes
|
||||
|
||||
3.7.0
|
||||
|
||||
* switch to dotenv for configuration file
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Deploying Nominatim
|
||||
|
||||
The Nominatim API is implemented as a PHP application. The `website/` directory
|
||||
in the build directory contains the configured website. You can serve this
|
||||
in the project directory contains the configured website. You can serve this
|
||||
in a production environment with any web server that is capable to run
|
||||
PHP scripts.
|
||||
|
||||
@@ -13,10 +13,11 @@ to run a web service. Please refer to the documentation of
|
||||
for background information on configuring the services.
|
||||
|
||||
!!! Note
|
||||
Throughout this page, we assume that your Nominatim build directory is
|
||||
located in `/srv/nominatim/build` and the source code in
|
||||
`/srv/nominatim/Nominatim`. If you have put it somewhere else, you
|
||||
need to adjust the commands and configuration accordingly.
|
||||
Throughout this page, we assume that your Nominatim project directory is
|
||||
located in `/srv/nominatim-project` and that you have installed Nominatim
|
||||
using the default installation prefix `/usr/local`. If you have put it
|
||||
somewhere else, you need to adjust the commands and configuration
|
||||
accordingly.
|
||||
|
||||
We further assume that your web server runs as user `www-data`. Older
|
||||
versions of CentOS may still use the user name `apache`. You also need
|
||||
@@ -29,7 +30,7 @@ web server user. You can check that the permissions are correct by accessing
|
||||
on of the php files as the web server user:
|
||||
|
||||
``` sh
|
||||
sudo -u www-data head -n 1 /srv/nominatim/build/website/search.php
|
||||
sudo -u www-data head -n 1 /srv/nominatim-project/website/search.php
|
||||
```
|
||||
|
||||
If this shows a permission error, then you need to adapt the permissions of
|
||||
@@ -40,11 +41,11 @@ web server access. At a minimum the following SELinux labelling should be done
|
||||
for Nominatim:
|
||||
|
||||
``` sh
|
||||
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/nominatim/Nominatim/(website|lib|settings)(/.*)?"
|
||||
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/nominatim/build/(website|settings)(/.*)?"
|
||||
sudo semanage fcontext -a -t lib_t "/srv/nominatim/build/module/nominatim.so"
|
||||
sudo restorecon -R -v /srv/nominatim/Nominatim
|
||||
sudo restorecon -R -v /srv/nominatim/build
|
||||
sudo semanage fcontext -a -t httpd_sys_content_t "/usr/local/nominatim/lib/lib-php(/.*)?"
|
||||
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/nominatim-project/website(/.*)?"
|
||||
sudo semanage fcontext -a -t lib_t "/srv/nominatim-project/module/nominatim.so"
|
||||
sudo restorecon -R -v /usr/local/lib/nominatim
|
||||
sudo restorecon -R -v /srv/nominatim-project
|
||||
```
|
||||
|
||||
## Nominatim with Apache
|
||||
@@ -65,13 +66,13 @@ Make sure your Apache configuration contains the required permissions for the
|
||||
directory and create an alias:
|
||||
|
||||
``` apache
|
||||
<Directory "/srv/nominatim/build/website">
|
||||
<Directory "/srv/nominatim-project/website">
|
||||
Options FollowSymLinks MultiViews
|
||||
AddType text/html .php
|
||||
DirectoryIndex search.php
|
||||
Require all granted
|
||||
</Directory>
|
||||
Alias /nominatim /srv/nominatim/build/website
|
||||
Alias /nominatim /srv/nominatim-project/website
|
||||
```
|
||||
|
||||
After making changes in the apache config you need to restart apache.
|
||||
@@ -110,7 +111,7 @@ Tell nginx that php files are special and to fastcgi_pass to the php-fpm
|
||||
unix socket by adding the location definition to the default configuration.
|
||||
|
||||
``` nginx
|
||||
root /srv/nominatim/build/website;
|
||||
root /srv/nominatim-project/website;
|
||||
index search.php;
|
||||
location / {
|
||||
try_files $uri $uri/ @php;
|
||||
|
||||
@@ -51,7 +51,7 @@ class Status
|
||||
$iDataDateEpoch = $this->oDB->getOne($sSQL);
|
||||
|
||||
if ($iDataDateEpoch === false) {
|
||||
throw Exception('Data date query failed '.$iDataDateEpoch->getMessage(), 705);
|
||||
throw new Exception('Import date is not available', 705);
|
||||
}
|
||||
|
||||
return $iDataDateEpoch;
|
||||
|
||||
@@ -227,3 +227,10 @@ function closestHouseNumber($aRow)
|
||||
|
||||
return max(min($aRow['endnumber'], $iHn), $aRow['startnumber']);
|
||||
}
|
||||
|
||||
if (!function_exists('array_key_last')) {
|
||||
function array_key_last(array $array)
|
||||
{
|
||||
if (!empty($array)) return key(array_slice($array, -1, 1, true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ if (isset($_SERVER['REQUEST_SCHEME'])
|
||||
.$_SERVER['HTTP_HOST'].$_SERVER['DOCUMENT_URI'].'/?'
|
||||
.http_build_query($aMoreParams);
|
||||
} else {
|
||||
$sMoreURL = '/search.php'.http_build_query($aMoreParams);
|
||||
$sMoreURL = '/search.php?'.http_build_query($aMoreParams);
|
||||
}
|
||||
|
||||
if (CONST_Debug) exit;
|
||||
|
||||
@@ -17,6 +17,23 @@ if ($sOutputFormat == 'json') {
|
||||
try {
|
||||
$oStatus = new Nominatim\Status($oDB);
|
||||
$oStatus->status();
|
||||
|
||||
if ($sOutputFormat == 'json') {
|
||||
$epoch = $oStatus->dataDate();
|
||||
$aResponse = array(
|
||||
'status' => 0,
|
||||
'message' => 'OK',
|
||||
'data_updated' => (new DateTime('@'.$epoch))->format(DateTime::RFC3339),
|
||||
'software_version' => CONST_NominatimVersion
|
||||
);
|
||||
$sDatabaseVersion = $oStatus->databaseVersion();
|
||||
if ($sDatabaseVersion) {
|
||||
$aResponse['database_version'] = $sDatabaseVersion;
|
||||
}
|
||||
javascript_renderData($aResponse);
|
||||
} else {
|
||||
echo 'OK';
|
||||
}
|
||||
} catch (Exception $oErr) {
|
||||
if ($sOutputFormat == 'json') {
|
||||
$aResponse = array(
|
||||
@@ -28,25 +45,4 @@ try {
|
||||
header('HTTP/1.0 500 Internal Server Error');
|
||||
echo 'ERROR: '.$oErr->getMessage();
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if ($sOutputFormat == 'json') {
|
||||
$epoch = $oStatus->dataDate();
|
||||
$aResponse = array(
|
||||
'status' => 0,
|
||||
'message' => 'OK',
|
||||
'data_updated' => (new DateTime('@'.$epoch))->format(DateTime::RFC3339),
|
||||
'software_version' => CONST_NominatimVersion
|
||||
);
|
||||
$sDatabaseVersion = $oStatus->databaseVersion();
|
||||
if ($sDatabaseVersion) {
|
||||
$aResponse['database_version'] = $sDatabaseVersion;
|
||||
}
|
||||
javascript_renderData($aResponse);
|
||||
} else {
|
||||
echo 'OK';
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--index only on parent_place_id
|
||||
CREATE INDEX {{sql.if_index_not_exists}} idx_location_property_tiger_place_id_imp
|
||||
CREATE INDEX {{sql.if_index_not_exists}} idx_location_property_tiger_parent_place_id_imp
|
||||
ON location_property_tiger_import (parent_place_id) {{db.tablespace.aux_index}};
|
||||
CREATE UNIQUE INDEX {{sql.if_index_not_exists}} idx_location_property_tiger_place_id_imp
|
||||
ON location_property_tiger_import (place_id) {{db.tablespace.aux_index}};
|
||||
|
||||
@@ -6,7 +6,9 @@ nominatim
|
||||
[-h] {import,freeze,replication,special-phrases,add-data,index,refresh,admin,export,serve,search,reverse,lookup,details,status,transition} ...
|
||||
.SH DESCRIPTION
|
||||
Command\-line tools for importing, updating, administrating and
|
||||
.br
|
||||
querying the Nominatim database.
|
||||
.br
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
@@ -69,6 +71,7 @@ usage: nominatim import [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--index-noanalyse]
|
||||
|
||||
Create a new Nominatim database from an OSM file.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -125,13 +128,21 @@ Do not perform analyse operations during index
|
||||
usage: nominatim freeze [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
|
||||
Make database read\-only.
|
||||
.br
|
||||
|
||||
.br
|
||||
About half of data in the Nominatim database is kept only to be able to
|
||||
.br
|
||||
keep the data up\-to\-date with new changes made in OpenStreetMap. This
|
||||
.br
|
||||
command drops all this data and only keeps the part needed for geocoding
|
||||
.br
|
||||
itself.
|
||||
.br
|
||||
|
||||
.br
|
||||
This command has the same effect as the `\-\-no\-updates` option for imports.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -160,6 +171,7 @@ usage: nominatim replication [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--socket-timeout SOCKET_TIMEOUT]
|
||||
|
||||
Update the database using an online replication service.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -213,6 +225,7 @@ usage: nominatim special-phrases [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--import-from-wiki]
|
||||
|
||||
Import special phrases.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -243,9 +256,13 @@ usage: nominatim add-data [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--use-main-api]
|
||||
|
||||
Add additional data from a file or an online source.
|
||||
.br
|
||||
|
||||
Data is only imported, not indexed. You need to call `nominatim\-update index`
|
||||
.br
|
||||
Data is only imported, not indexed. You need to call `nominatim index`
|
||||
.br
|
||||
to complete the process.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -300,6 +317,7 @@ usage: nominatim index [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--maxrank RANK]
|
||||
|
||||
Reindex all new and modified data.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -344,8 +362,11 @@ usage: nominatim refresh [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--enable-debug-statements]
|
||||
|
||||
Recompute auxiliary data used by the indexing process.
|
||||
.br
|
||||
|
||||
.br
|
||||
These functions must not be run in parallel with other update commands.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -409,6 +430,7 @@ usage: nominatim admin [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--osm-id OSM_ID | --place-id PLACE_ID]
|
||||
|
||||
Analyse and maintain the database.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -471,6 +493,7 @@ usage: nominatim export [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--restrict-to-osm-relation ID]
|
||||
|
||||
Export addresses as CSV file from the database.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -528,12 +551,19 @@ usage: nominatim serve [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--server SERVER]
|
||||
|
||||
Start a simple web server for serving the API.
|
||||
.br
|
||||
|
||||
.br
|
||||
This command starts the built\-in PHP webserver to serve the website
|
||||
.br
|
||||
from the current project directory. This webserver is only suitable
|
||||
.br
|
||||
for testing and develop. Do not use it in production setups!
|
||||
.br
|
||||
|
||||
.br
|
||||
By the default, the webserver can be accessed at: http://127.0.0.1:8088
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -572,6 +602,7 @@ usage: nominatim search [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--viewbox X1,Y1,X2,Y2] [--bounded] [--no-dedupe]
|
||||
|
||||
Execute API search query.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -682,6 +713,7 @@ usage: nominatim reverse [-h] [-q] [-v] [--project-dir DIR] [-j NUM] --lat LAT
|
||||
[--polygon-threshold TOLERANCE]
|
||||
|
||||
Execute API reverse query.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -751,6 +783,7 @@ usage: nominatim lookup [-h] [-q] [-v] [--project-dir DIR] [-j NUM] --id OSMID
|
||||
[--polygon-threshold TOLERANCE]
|
||||
|
||||
Execute API lookup query.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -812,6 +845,7 @@ usage: nominatim details [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--lang LANGS]
|
||||
|
||||
Execute API details query.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -885,6 +919,7 @@ usage: nominatim status [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--format {text,json}]
|
||||
|
||||
Execute API status query.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
@@ -921,6 +956,7 @@ usage: nominatim transition [-h] [-q] [-v] [--project-dir DIR] [-j NUM]
|
||||
[--tiger-data FILE]
|
||||
|
||||
Internal functions for code transition. Do not use.
|
||||
.br
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ class UpdateAddData:
|
||||
"""\
|
||||
Add additional data from a file or an online source.
|
||||
|
||||
Data is only imported, not indexed. You need to call `nominatim-update index`
|
||||
Data is only imported, not indexed. You need to call `nominatim index`
|
||||
to complete the process.
|
||||
"""
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ class UpdateReplication:
|
||||
if state is not replication.UpdateState.NO_CHANGES:
|
||||
status.log_status(conn, start, 'import')
|
||||
batchdate, _, _ = status.get_status(conn)
|
||||
conn.commit()
|
||||
|
||||
if state is not replication.UpdateState.NO_CHANGES and args.do_index:
|
||||
index_start = dt.datetime.now(dt.timezone.utc)
|
||||
@@ -125,6 +126,7 @@ class UpdateReplication:
|
||||
with connect(args.config.get_libpq_dsn()) as conn:
|
||||
status.set_indexed(conn, True)
|
||||
status.log_status(conn, index_start, 'index')
|
||||
conn.commit()
|
||||
else:
|
||||
index_start = None
|
||||
|
||||
|
||||
@@ -105,11 +105,11 @@ class SetupAll:
|
||||
LOG.error('Wikipedia importance dump file not found. '
|
||||
'Will be using default importances.')
|
||||
|
||||
if args.continue_at is None or args.continue_at == 'load-data':
|
||||
LOG.warning('Initialise tables')
|
||||
with connect(args.config.get_libpq_dsn()) as conn:
|
||||
database_import.truncate_data_tables(conn, args.config.MAX_WORD_FREQUENCY)
|
||||
|
||||
if args.continue_at is None or args.continue_at == 'load-data':
|
||||
LOG.warning('Load data into placex table')
|
||||
database_import.load_data(args.config.get_libpq_dsn(),
|
||||
args.data_dir,
|
||||
@@ -120,6 +120,9 @@ class SetupAll:
|
||||
nominatim_env=args, throw_on_fail=not args.ignore_errors)
|
||||
|
||||
if args.continue_at is None or args.continue_at in ('load-data', 'indexing'):
|
||||
if args.continue_at is not None and args.continue_at != 'load-data':
|
||||
with connect(args.config.get_libpq_dsn()) as conn:
|
||||
SetupAll._create_pending_index(conn, args.config.TABLESPACE_ADDRESS_INDEX)
|
||||
LOG.warning('Indexing places')
|
||||
indexer = Indexer(args.config.get_libpq_dsn(),
|
||||
args.threads or psutil.cpu_count() or 1)
|
||||
@@ -149,3 +152,25 @@ class SetupAll:
|
||||
'{0[0]}.{0[1]}.{0[2]}-{0[3]}'.format(NOMINATIM_VERSION))
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _create_pending_index(conn, tablespace):
|
||||
""" Add a supporting index for finding places still to be indexed.
|
||||
|
||||
This index is normally created at the end of the import process
|
||||
for later updates. When indexing was partially done, then this
|
||||
index can greatly improve speed going through already indexed data.
|
||||
"""
|
||||
if conn.index_exists('idx_placex_pendingsector'):
|
||||
return
|
||||
|
||||
with conn.cursor() as cur:
|
||||
LOG.warning('Creating support index')
|
||||
if tablespace:
|
||||
tablespace = 'TABLESPACE ' + tablespace
|
||||
cur.execute("""CREATE INDEX idx_placex_pendingsector
|
||||
ON placex USING BTREE (rank_address,geometry_sector)
|
||||
{} WHERE indexed_status > 0
|
||||
""".format(tablespace))
|
||||
conn.commit()
|
||||
|
||||
@@ -30,7 +30,7 @@ class Configuration:
|
||||
self.project_dir = project_dir
|
||||
self.config_dir = config_dir
|
||||
self._config = dotenv_values(str((config_dir / 'env.defaults').resolve()))
|
||||
if project_dir is not None:
|
||||
if project_dir is not None and (project_dir / '.env').is_file():
|
||||
self._config.update(dotenv_values(str((project_dir / '.env').resolve())))
|
||||
|
||||
# Add defaults for variables that are left empty to set the default.
|
||||
|
||||
@@ -14,7 +14,7 @@ from psycopg2.extras import wait_select
|
||||
try:
|
||||
import psycopg2.errors # pylint: disable=no-name-in-module,import-error
|
||||
__has_psycopg2_errors__ = True
|
||||
except ModuleNotFoundError:
|
||||
except ImportError:
|
||||
__has_psycopg2_errors__ = False
|
||||
|
||||
LOG = logging.getLogger()
|
||||
|
||||
@@ -9,6 +9,7 @@ from ..tools.exec_utils import get_url
|
||||
from ..errors import UsageError
|
||||
|
||||
LOG = logging.getLogger()
|
||||
ISODATE_FORMAT = '%Y-%m-%dT%H:%M:%S'
|
||||
|
||||
def compute_database_date(conn):
|
||||
""" Determine the date of the database from the newest object in the
|
||||
@@ -34,9 +35,9 @@ def compute_database_date(conn):
|
||||
"URL used: %s", node_url)
|
||||
raise UsageError("Bad API data.")
|
||||
|
||||
LOG.debug("Found timestamp %s", match[1])
|
||||
LOG.debug("Found timestamp %s", match.group(1))
|
||||
|
||||
return dt.datetime.fromisoformat(match[1]).replace(tzinfo=dt.timezone.utc)
|
||||
return dt.datetime.strptime(match.group(1), ISODATE_FORMAT).replace(tzinfo=dt.timezone.utc)
|
||||
|
||||
|
||||
def set_status(conn, date, seq=None, indexed=True):
|
||||
|
||||
@@ -94,6 +94,9 @@ def _get_indexes(conn):
|
||||
indexes.extend(('idx_search_name_nameaddress_vector',
|
||||
'idx_search_name_name_vector',
|
||||
'idx_search_name_centroid'))
|
||||
if conn.server_version_tuple() >= (11, 0, 0):
|
||||
indexes.extend(('idx_placex_housenumber',
|
||||
'idx_osmline_parent_osm_id_with_hnr'))
|
||||
if conn.table_exists('place'):
|
||||
indexes.extend(('idx_placex_pendingsector',
|
||||
'idx_location_area_country_place_id',
|
||||
|
||||
@@ -18,16 +18,16 @@ def run_legacy_script(script, *args, nominatim_env=None, throw_on_fail=False):
|
||||
then throw a `CalledProcessError` on a non-zero exit.
|
||||
"""
|
||||
cmd = ['/usr/bin/env', 'php', '-Cq',
|
||||
nominatim_env.phplib_dir / 'admin' / script]
|
||||
str(nominatim_env.phplib_dir / 'admin' / script)]
|
||||
cmd.extend([str(a) for a in args])
|
||||
|
||||
env = nominatim_env.config.get_os_env()
|
||||
env['NOMINATIM_DATADIR'] = str(nominatim_env.data_dir)
|
||||
env['NOMINATIM_SQLDIR'] = str(nominatim_env.sqllib_dir)
|
||||
env['NOMINATIM_CONFIGDIR'] = str(nominatim_env.config_dir)
|
||||
env['NOMINATIM_DATABASE_MODULE_SRC_PATH'] = nominatim_env.module_dir
|
||||
env['NOMINATIM_DATABASE_MODULE_SRC_PATH'] = str(nominatim_env.module_dir)
|
||||
if not env['NOMINATIM_OSM2PGSQL_BINARY']:
|
||||
env['NOMINATIM_OSM2PGSQL_BINARY'] = nominatim_env.osm2pgsql_path
|
||||
env['NOMINATIM_OSM2PGSQL_BINARY'] = str(nominatim_env.osm2pgsql_path)
|
||||
|
||||
proc = subprocess.run(cmd, cwd=str(nominatim_env.project_dir), env=env,
|
||||
check=throw_on_fail)
|
||||
@@ -99,7 +99,7 @@ def run_osm2pgsql(options):
|
||||
""" Run osm2pgsql with the given options.
|
||||
"""
|
||||
env = get_pg_env(options['dsn'])
|
||||
cmd = [options['osm2pgsql'],
|
||||
cmd = [str(options['osm2pgsql']),
|
||||
'--hstore', '--latlon', '--slim',
|
||||
'--with-forward-dependencies', 'false',
|
||||
'--log-progress', 'true',
|
||||
|
||||
@@ -13,7 +13,7 @@ from ..errors import UsageError
|
||||
try:
|
||||
from osmium.replication.server import ReplicationServer
|
||||
from osmium import WriteHandler
|
||||
except ModuleNotFoundError as exc:
|
||||
except ImportError as exc:
|
||||
logging.getLogger().fatal("pyosmium not installed. Replication functions not available.\n"
|
||||
"To install pyosmium via pip: pip3 install osmium")
|
||||
raise UsageError("replication tools not available") from exc
|
||||
|
||||
@@ -27,7 +27,7 @@ class SpecialPhrasesImporter():
|
||||
self.black_list, self.white_list = self._load_white_and_black_lists()
|
||||
#Compile the regex here to increase performances.
|
||||
self.occurence_pattern = re.compile(
|
||||
r'\| ([^\|]+) \|\| ([^\|]+) \|\| ([^\|]+) \|\| ([^\|]+) \|\| ([\-YN])'
|
||||
r'\| *([^\|]+) *\|\| *([^\|]+) *\|\| *([^\|]+) *\|\| *([^\|]+) *\|\| *([\-YN])'
|
||||
)
|
||||
self.sanity_check_pattern = re.compile(r'^\w+$')
|
||||
self.transliterator = Transliterator.createFromRules("special-phrases normalizer",
|
||||
@@ -65,7 +65,7 @@ class SpecialPhrasesImporter():
|
||||
if self.config.PHRASE_CONFIG:
|
||||
settings_path = self._convert_php_settings_if_needed(self.config.PHRASE_CONFIG)
|
||||
|
||||
with open(settings_path, "r") as json_settings:
|
||||
with settings_path.open("r") as json_settings:
|
||||
settings = json.load(json_settings)
|
||||
return settings['blackList'], settings['whiteList']
|
||||
|
||||
@@ -80,7 +80,7 @@ class SpecialPhrasesImporter():
|
||||
'et', 'eu', 'fa', 'fi', 'fr', 'gl', 'hr', 'hu',
|
||||
'ia', 'is', 'it', 'ja', 'mk', 'nl', 'no', 'pl',
|
||||
'ps', 'pt', 'ru', 'sk', 'sl', 'sv', 'uk', 'vi']
|
||||
return self.config.LANGUAGES or default_languages
|
||||
return self.config.LANGUAGES.split(',') if self.config.LANGUAGES else default_languages
|
||||
|
||||
@staticmethod
|
||||
def _get_wiki_content(lang):
|
||||
@@ -102,8 +102,10 @@ class SpecialPhrasesImporter():
|
||||
class_matchs = self.sanity_check_pattern.findall(phrase_class)
|
||||
|
||||
if len(class_matchs) < 1 or len(type_matchs) < 1:
|
||||
raise UsageError("Bad class/type for language {}: {}={}".format(
|
||||
lang, phrase_class, phrase_type))
|
||||
LOG.warning("Bad class/type for language %s: %s=%s. It will not be imported",
|
||||
lang, phrase_class, phrase_type)
|
||||
return False
|
||||
return True
|
||||
|
||||
def _process_xml_content(self, xml_content, lang):
|
||||
"""
|
||||
|
||||
@@ -61,6 +61,20 @@ def handle_threaded_sql_statements(sel, file):
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
LOG.info('Wrong SQL statement: %s', exc)
|
||||
|
||||
def handle_unregister_connection_pool(sel, place_threads):
|
||||
""" Handles unregistering pool of connections
|
||||
"""
|
||||
|
||||
while place_threads > 0:
|
||||
for key, _ in sel.select(1):
|
||||
conn = key.data
|
||||
sel.unregister(conn)
|
||||
try:
|
||||
conn.wait()
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
LOG.info('Wrong SQL statement: %s', exc)
|
||||
conn.close()
|
||||
place_threads -= 1
|
||||
|
||||
def add_tiger_data(dsn, data_dir, threads, config, sqllib_dir):
|
||||
""" Import tiger data from directory or tar file
|
||||
@@ -95,13 +109,7 @@ def add_tiger_data(dsn, data_dir, threads, config, sqllib_dir):
|
||||
handle_threaded_sql_statements(sel, file)
|
||||
|
||||
# Unregistering pool of database connections
|
||||
while place_threads > 0:
|
||||
for key, _ in sel.select(1):
|
||||
conn = key.data
|
||||
sel.unregister(conn)
|
||||
conn.wait()
|
||||
conn.close()
|
||||
place_threads -= 1
|
||||
handle_unregister_connection_pool(sel, place_threads)
|
||||
|
||||
if tar:
|
||||
tar.close()
|
||||
|
||||
@@ -19,6 +19,11 @@ OSM_NODE_DATA = """\
|
||||
</osm>
|
||||
"""
|
||||
|
||||
def iso_date(date):
|
||||
return dt.datetime.strptime(date, nominatim.db.status.ISODATE_FORMAT)\
|
||||
.replace(tzinfo=dt.timezone.utc)
|
||||
|
||||
|
||||
def test_compute_database_date_valid(monkeypatch, status_table, place_row, temp_db_conn):
|
||||
place_row(osm_type='N', osm_id=45673)
|
||||
|
||||
@@ -32,7 +37,7 @@ def test_compute_database_date_valid(monkeypatch, status_table, place_row, temp_
|
||||
date = nominatim.db.status.compute_database_date(temp_db_conn)
|
||||
|
||||
assert requested_url == ['https://www.openstreetmap.org/api/0.6/node/45673/1']
|
||||
assert date == dt.datetime.fromisoformat('2006-01-27T22:09:10').replace(tzinfo=dt.timezone.utc)
|
||||
assert date == iso_date('2006-01-27T22:09:10')
|
||||
|
||||
|
||||
def test_compute_database_broken_api(monkeypatch, status_table, place_row, temp_db_conn):
|
||||
|
||||
@@ -17,13 +17,11 @@ def test_check_sanity_class(special_phrases_importer):
|
||||
If a wrong class or type is given, an UsageError should raise.
|
||||
If a good class and type are given, nothing special happens.
|
||||
"""
|
||||
with pytest.raises(UsageError):
|
||||
special_phrases_importer._check_sanity('en', '', 'type')
|
||||
|
||||
with pytest.raises(UsageError):
|
||||
special_phrases_importer._check_sanity('en', 'class', '')
|
||||
assert not special_phrases_importer._check_sanity('en', '', 'type')
|
||||
assert not special_phrases_importer._check_sanity('en', 'class', '')
|
||||
|
||||
special_phrases_importer._check_sanity('en', 'class', 'type')
|
||||
assert special_phrases_importer._check_sanity('en', 'class', 'type')
|
||||
|
||||
def test_load_white_and_black_lists(special_phrases_importer):
|
||||
"""
|
||||
|
||||
@@ -41,7 +41,8 @@ def test_init_replication_success(monkeypatch, status_table, place_row, temp_db_
|
||||
|
||||
temp_db_cursor.execute("SELECT * FROM import_status")
|
||||
|
||||
expected_date = dt.datetime.fromisoformat('2006-01-27T19:09:10').replace(tzinfo=dt.timezone.utc)
|
||||
expected_date = dt.datetime.strptime('2006-01-27T19:09:10', status.ISODATE_FORMAT)\
|
||||
.replace(tzinfo=dt.timezone.utc)
|
||||
assert temp_db_cursor.rowcount == 1
|
||||
assert temp_db_cursor.fetchone() == [expected_date, 234, True]
|
||||
|
||||
|
||||
@@ -16,11 +16,24 @@ def test_add_tiger_data(dsn, src_dir, def_config, tmp_path, sql_preprocessor,
|
||||
temp_db_cursor.execute('CREATE EXTENSION postgis')
|
||||
temp_db_cursor.execute('CREATE TABLE place (id INT)')
|
||||
sqlfile = tmp_path / '1010.sql'
|
||||
sqlfile.write_text("""INSERT INTO place values (1)""")
|
||||
sqlfile.write_text("""INSERT INTO place values (1);
|
||||
INSERT INTO non_existant_table values (1);""")
|
||||
tiger_data.add_tiger_data(dsn, str(tmp_path), threads, def_config, src_dir / 'lib-sql')
|
||||
|
||||
assert temp_db_cursor.table_rows('place') == 1
|
||||
|
||||
@pytest.mark.parametrize("threads", (1, 5))
|
||||
def test_add_tiger_data_bad_file(dsn, src_dir, def_config, tmp_path, sql_preprocessor,
|
||||
temp_db_cursor, threads, temp_db):
|
||||
temp_db_cursor.execute('CREATE EXTENSION hstore')
|
||||
temp_db_cursor.execute('CREATE EXTENSION postgis')
|
||||
temp_db_cursor.execute('CREATE TABLE place (id INT)')
|
||||
sqlfile = tmp_path / '1010.txt'
|
||||
sqlfile.write_text("""Random text""")
|
||||
tiger_data.add_tiger_data(dsn, str(tmp_path), threads, def_config, src_dir / 'lib-sql')
|
||||
|
||||
assert temp_db_cursor.table_rows('place') == 0
|
||||
|
||||
@pytest.mark.parametrize("threads", (1, 5))
|
||||
def test_add_tiger_data_tarfile(dsn, src_dir, def_config, tmp_path,
|
||||
temp_db_cursor, threads, temp_db, sql_preprocessor):
|
||||
@@ -28,10 +41,26 @@ def test_add_tiger_data_tarfile(dsn, src_dir, def_config, tmp_path,
|
||||
temp_db_cursor.execute('CREATE EXTENSION postgis')
|
||||
temp_db_cursor.execute('CREATE TABLE place (id INT)')
|
||||
sqlfile = tmp_path / '1010.sql'
|
||||
sqlfile.write_text("""INSERT INTO place values (1)""")
|
||||
sqlfile.write_text("""INSERT INTO place values (1);
|
||||
INSERT INTO non_existant_table values (1);""")
|
||||
tar = tarfile.open("sample.tar.gz", "w:gz")
|
||||
tar.add(sqlfile)
|
||||
tar.close()
|
||||
tiger_data.add_tiger_data(dsn, str(src_dir / 'sample.tar.gz'), threads, def_config, src_dir / 'lib-sql')
|
||||
|
||||
assert temp_db_cursor.table_rows('place') == 1
|
||||
assert temp_db_cursor.table_rows('place') == 1
|
||||
|
||||
@pytest.mark.parametrize("threads", (1, 5))
|
||||
def test_add_tiger_data_bad_tarfile(dsn, src_dir, def_config, tmp_path,
|
||||
temp_db_cursor, threads, temp_db, sql_preprocessor):
|
||||
temp_db_cursor.execute('CREATE EXTENSION hstore')
|
||||
temp_db_cursor.execute('CREATE EXTENSION postgis')
|
||||
temp_db_cursor.execute('CREATE TABLE place (id INT)')
|
||||
sqlfile = tmp_path / '1010.txt'
|
||||
sqlfile.write_text("""Random text""")
|
||||
tar = tarfile.open("sample.tar.gz", "w:gz")
|
||||
tar.add(sqlfile)
|
||||
tar.close()
|
||||
tiger_data.add_tiger_data(dsn, str(src_dir / 'sample.tar.gz'), threads, def_config, src_dir / 'lib-sql')
|
||||
|
||||
assert temp_db_cursor.table_rows('place') == 0
|
||||
@@ -42,7 +42,7 @@
|
||||
python3-pip python3-setuptools python3-devel \
|
||||
expat-devel zlib-devel libicu-dev
|
||||
|
||||
pip3 install --user psycopg2 python-dotenv psutil Jinja2 PyICU argparse-manpage
|
||||
pip3 install --user psycopg2 python-dotenv psutil Jinja2 PyICU
|
||||
|
||||
|
||||
#
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
python3-pip python3-setuptools python3-devel \
|
||||
expat-devel zlib-devel libicu-dev
|
||||
|
||||
pip3 install --user psycopg2 python-dotenv psutil Jinja2 PyICU argparse-manpage
|
||||
pip3 install --user psycopg2 python-dotenv psutil Jinja2 PyICU
|
||||
|
||||
|
||||
#
|
||||
|
||||
@@ -30,8 +30,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
|
||||
postgresql-server-dev-10 postgresql-10-postgis-2.4 \
|
||||
postgresql-contrib-10 postgresql-10-postgis-scripts \
|
||||
php php-pgsql php-intl libicu-dev python3-pip \
|
||||
python3-psycopg2 python3-psutil python3-jinja2 python3-icu git \
|
||||
python3-argparse-manpage
|
||||
python3-psycopg2 python3-psutil python3-jinja2 python3-icu git
|
||||
|
||||
# The python-dotenv package that comes with Ubuntu 18.04 is too old, so
|
||||
# install the latest version from pip:
|
||||
|
||||
@@ -33,8 +33,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
|
||||
postgresql-server-dev-12 postgresql-12-postgis-3 \
|
||||
postgresql-contrib-12 postgresql-12-postgis-3-scripts \
|
||||
php php-pgsql php-intl libicu-dev python3-dotenv \
|
||||
python3-psycopg2 python3-psutil python3-jinja2 python3-icu git \
|
||||
python3-argparse-manpage
|
||||
python3-psycopg2 python3-psutil python3-jinja2 python3-icu git
|
||||
|
||||
#
|
||||
# System Configuration
|
||||
|
||||
Reference in New Issue
Block a user