mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-16 15:47:58 +00:00
Compare commits
442 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
748fa3e28f | ||
|
|
7ef0239f19 | ||
|
|
2daa4ed813 | ||
|
|
8714fa7dec | ||
|
|
896421fe9f | ||
|
|
4e6c75040e | ||
|
|
7448d3f171 | ||
|
|
5e5713b90f | ||
|
|
9785aff76c | ||
|
|
f4e958a66d | ||
|
|
5a5691b5b7 | ||
|
|
9848381a04 | ||
|
|
623d58b67e | ||
|
|
6985abc3fd | ||
|
|
0628aa887f | ||
|
|
c13094acfd | ||
|
|
308bfcbf25 | ||
|
|
de0ad657ba | ||
|
|
13674c3939 | ||
|
|
b9cc47ee67 | ||
|
|
6db110f5cb | ||
|
|
af81c6aa94 | ||
|
|
54393addd3 | ||
|
|
e3fb706c65 | ||
|
|
2dd7f0156a | ||
|
|
5b8672c10a | ||
|
|
7a14792e21 | ||
|
|
d88c484fa1 | ||
|
|
bdd90e890b | ||
|
|
b5fc5e0a71 | ||
|
|
002fa35b92 | ||
|
|
d023578f90 | ||
|
|
1876fe42c9 | ||
|
|
86acaa5264 | ||
|
|
d898f9aabf | ||
|
|
33c919ab09 | ||
|
|
deca74bc3a | ||
|
|
74b3251c7a | ||
|
|
65afe13f0a | ||
|
|
bd4b1b2d08 | ||
|
|
1a1526ec30 | ||
|
|
6830b1229e | ||
|
|
e7c8b498d1 | ||
|
|
b15b996cc4 | ||
|
|
d8ade1c527 | ||
|
|
6043cd5ad8 | ||
|
|
86d5209118 | ||
|
|
c629573230 | ||
|
|
291a161cc6 | ||
|
|
4c7145c293 | ||
|
|
4d4b95923e | ||
|
|
71e6d5f9a6 | ||
|
|
446a5a95bc | ||
|
|
19edbd3581 | ||
|
|
166737fb76 | ||
|
|
b6be33cded | ||
|
|
c80637b05c | ||
|
|
3ec67b9193 | ||
|
|
40debbc7b5 | ||
|
|
ccecabfbf4 | ||
|
|
1e30e578e0 | ||
|
|
29e9683293 | ||
|
|
8138729aea | ||
|
|
9bb81731f8 | ||
|
|
050b0a2ced | ||
|
|
3bb903cf92 | ||
|
|
41afcaddd5 | ||
|
|
8c7fa0213f | ||
|
|
49b5e4dbad | ||
|
|
c8e79397f5 | ||
|
|
43eedfd253 | ||
|
|
ee1b25820e | ||
|
|
193cf66328 | ||
|
|
77e55fade2 | ||
|
|
09f1661638 | ||
|
|
e841422b1f | ||
|
|
97ade7dd7e | ||
|
|
e24f53cb34 | ||
|
|
62b7b76662 | ||
|
|
c7434264ae | ||
|
|
026081e131 | ||
|
|
47586fd861 | ||
|
|
8e79ece203 | ||
|
|
a23bd80a31 | ||
|
|
f4a86ff4c4 | ||
|
|
73c151b3ac | ||
|
|
0a10be6586 | ||
|
|
1e3bf9729e | ||
|
|
924d3a8d6e | ||
|
|
2a07bb8a7f | ||
|
|
b3186d07f5 | ||
|
|
ecee3828b3 | ||
|
|
a64f992092 | ||
|
|
5682d1688d | ||
|
|
57b35654e7 | ||
|
|
a67edd328e | ||
|
|
20a4cab57e | ||
|
|
ab3b556144 | ||
|
|
1649191ffd | ||
|
|
41fce277cd | ||
|
|
39c4c7fce8 | ||
|
|
3a696e1895 | ||
|
|
a793f698f3 | ||
|
|
889637321b | ||
|
|
a52455f160 | ||
|
|
9358243b66 | ||
|
|
9e54d1d6eb | ||
|
|
1aaeee19a1 | ||
|
|
6153ad3b31 | ||
|
|
7e3af2debc | ||
|
|
450a12c6be | ||
|
|
196c55e341 | ||
|
|
2c3317f582 | ||
|
|
e0c066d850 | ||
|
|
e1cbca2572 | ||
|
|
e1095205e4 | ||
|
|
e5c79a1d1f | ||
|
|
6551399bcc | ||
|
|
c48fb88e6b | ||
|
|
e04838cc71 | ||
|
|
0916d72ddf | ||
|
|
a933421860 | ||
|
|
66d7f1a058 | ||
|
|
e77a07cbb3 | ||
|
|
c897b96c41 | ||
|
|
679e4c47ce | ||
|
|
13ab03a03a | ||
|
|
56962deb30 | ||
|
|
e86516bbaf | ||
|
|
b6acd24e5a | ||
|
|
e31cd9717c | ||
|
|
6eb6f35f24 | ||
|
|
e9decd2574 | ||
|
|
2fd9ffda43 | ||
|
|
a84a7a70f3 | ||
|
|
dcab7a19e5 | ||
|
|
d4c78a982e | ||
|
|
7716e0bc92 | ||
|
|
5dea0658e4 | ||
|
|
cfd03d7be3 | ||
|
|
9240e83802 | ||
|
|
2c07d5e000 | ||
|
|
ea5fe54c6b | ||
|
|
08d1ec09cc | ||
|
|
b8db8301df | ||
|
|
d18bd14045 | ||
|
|
65500927c2 | ||
|
|
4a5a997e18 | ||
|
|
fadffeaa2d | ||
|
|
c0e4a74c71 | ||
|
|
b2be8c3ab7 | ||
|
|
5252051291 | ||
|
|
ccaea09a65 | ||
|
|
b2c1d086b5 | ||
|
|
3a787df934 | ||
|
|
635ce30db5 | ||
|
|
201f618cc7 | ||
|
|
81922fc057 | ||
|
|
b9a58b8f24 | ||
|
|
b75aadfb6b | ||
|
|
80a74181e4 | ||
|
|
6f4f19004c | ||
|
|
e2f23e391b | ||
|
|
f2debbef19 | ||
|
|
21a3fc4b0f | ||
|
|
0e9e2bbdca | ||
|
|
4f2d73aa7c | ||
|
|
c20f8b13a5 | ||
|
|
7f4e7a2579 | ||
|
|
82a0e23265 | ||
|
|
e36e485698 | ||
|
|
ddb7296663 | ||
|
|
604706a827 | ||
|
|
c594644aa7 | ||
|
|
47f94c6988 | ||
|
|
c56c09e2c0 | ||
|
|
65bf6dbff7 | ||
|
|
7273b58bbe | ||
|
|
adb6ea546f | ||
|
|
3ff8bb55a7 | ||
|
|
99c58706d3 | ||
|
|
523873fe16 | ||
|
|
de01c5b23d | ||
|
|
57dc135844 | ||
|
|
e24129febe | ||
|
|
b27926fd4d | ||
|
|
cfb0f3f94c | ||
|
|
eaee6b700d | ||
|
|
032f24bfef | ||
|
|
d93209ee48 | ||
|
|
eb79e655e6 | ||
|
|
4f3074e538 | ||
|
|
8312e8f539 | ||
|
|
d4daa0c4fa | ||
|
|
a9ad69efae | ||
|
|
0a45dbf5f6 | ||
|
|
a61f852cd2 | ||
|
|
26ba5bf0be | ||
|
|
702f9477ab | ||
|
|
179542f938 | ||
|
|
b77e2503f5 | ||
|
|
1542a006cb | ||
|
|
bb1c3f23ab | ||
|
|
8650e0fedd | ||
|
|
abac5d8ebd | ||
|
|
aa7c8b6b5b | ||
|
|
e69115fd8f | ||
|
|
7b1f35426d | ||
|
|
6757e1b865 | ||
|
|
c72e6a93dc | ||
|
|
c0b4411337 | ||
|
|
0e613a362e | ||
|
|
4123a3fd6b | ||
|
|
087522c601 | ||
|
|
fb51d51582 | ||
|
|
f5641037cf | ||
|
|
39580057fc | ||
|
|
a855ffe58e | ||
|
|
42d473968f | ||
|
|
8a2e401025 | ||
|
|
a912b3448f | ||
|
|
8b896f37f3 | ||
|
|
6bf90eb22f | ||
|
|
421174ce0c | ||
|
|
1982978f74 | ||
|
|
6fd2887543 | ||
|
|
44ee8d9ce3 | ||
|
|
bf77b444bf | ||
|
|
a7da0c90bf | ||
|
|
6238ae6032 | ||
|
|
d437a14f25 | ||
|
|
e1be3d9f48 | ||
|
|
e686ce8680 | ||
|
|
93c26a0e65 | ||
|
|
02550cc4dc | ||
|
|
b243aa84e2 | ||
|
|
cfed4bc204 | ||
|
|
4a321487f3 | ||
|
|
74c06ef877 | ||
|
|
51155b639b | ||
|
|
775fdeb8e4 | ||
|
|
eb0b3bfa4c | ||
|
|
2a784fa3d4 | ||
|
|
5c40100b57 | ||
|
|
ae5cc28a1a | ||
|
|
cf39e07dba | ||
|
|
e49ed1bb13 | ||
|
|
3887423381 | ||
|
|
f05ea577f4 | ||
|
|
effd8e12af | ||
|
|
89c157a6c1 | ||
|
|
832547f192 | ||
|
|
36fdfd92ad | ||
|
|
cd6dcfa574 | ||
|
|
8a796db3c9 | ||
|
|
87b6810eba | ||
|
|
50c994be93 | ||
|
|
797c2d1e74 | ||
|
|
d7c469d94e | ||
|
|
3b7baca46c | ||
|
|
0957bd27c6 | ||
|
|
5464dec057 | ||
|
|
feb458f8dd | ||
|
|
9c1e0c49bf | ||
|
|
36f2afea8a | ||
|
|
5c187e131a | ||
|
|
cb68a2cdd2 | ||
|
|
3499ed7b82 | ||
|
|
9ff24b9107 | ||
|
|
ee7a6e8f92 | ||
|
|
88d623b631 | ||
|
|
2a97ce6aed | ||
|
|
bb403e2e58 | ||
|
|
496d6bf168 | ||
|
|
b00169e634 | ||
|
|
9be58ffc7c | ||
|
|
1fb847a5ad | ||
|
|
8a823d1361 | ||
|
|
ab30a69ad9 | ||
|
|
0a95bdc5f5 | ||
|
|
d594bb238b | ||
|
|
0d179b8c97 | ||
|
|
1b33999f10 | ||
|
|
3f06d9d3ba | ||
|
|
7da9178b83 | ||
|
|
a766240c06 | ||
|
|
a827367a2f | ||
|
|
4f75f4cb6e | ||
|
|
975c30afba | ||
|
|
ca92442601 | ||
|
|
77ca079688 | ||
|
|
665de339e5 | ||
|
|
84495489d9 | ||
|
|
8eb0e09ce3 | ||
|
|
2ab43f6367 | ||
|
|
b14bc75dc4 | ||
|
|
860acbf6af | ||
|
|
10c5d7f6f6 | ||
|
|
e842d8793c | ||
|
|
348a3082c9 | ||
|
|
033b9590bd | ||
|
|
95961d098d | ||
|
|
7a50d2f996 | ||
|
|
6fef943e49 | ||
|
|
76b9eb8098 | ||
|
|
d45524cbfb | ||
|
|
aa9fff9199 | ||
|
|
1a47376040 | ||
|
|
051998dd80 | ||
|
|
cf4a44aaf7 | ||
|
|
85c72cdccd | ||
|
|
3a41b0dfbf | ||
|
|
6436bab1be | ||
|
|
91e1e4d614 | ||
|
|
af93973237 | ||
|
|
2e08a61565 | ||
|
|
0adb8cb765 | ||
|
|
f71e9dd187 | ||
|
|
186a633185 | ||
|
|
d1b1acaf1d | ||
|
|
ff6c3a705b | ||
|
|
badd2e46aa | ||
|
|
98e5ba6b61 | ||
|
|
2156fb1ad7 | ||
|
|
92095c9247 | ||
|
|
524bd47315 | ||
|
|
c3e21ea388 | ||
|
|
f0d962f8a0 | ||
|
|
e4963256e1 | ||
|
|
362f259f47 | ||
|
|
8b91284f7f | ||
|
|
2a0c7fb57a | ||
|
|
2fecc0c465 | ||
|
|
94d795883f | ||
|
|
f0f6fcf256 | ||
|
|
28041cbbd9 | ||
|
|
821949f087 | ||
|
|
0fcab79486 | ||
|
|
234b1b0293 | ||
|
|
f07d620ee8 | ||
|
|
190a72cab5 | ||
|
|
1a4f369e2b | ||
|
|
ce112f7c20 | ||
|
|
4e0e0c1797 | ||
|
|
54ef9105d0 | ||
|
|
9e1421fb6c | ||
|
|
2ba9c11dd0 | ||
|
|
db719d489f | ||
|
|
7a5aab61ae | ||
|
|
7b4806b2e8 | ||
|
|
a10f537131 | ||
|
|
89c556d163 | ||
|
|
b03be15442 | ||
|
|
7879ad44cd | ||
|
|
131527bdab | ||
|
|
a244c41ea7 | ||
|
|
a32f6c66b8 | ||
|
|
b4f0b8b728 | ||
|
|
af06d31d21 | ||
|
|
d01d0c13f4 | ||
|
|
be268f95e6 | ||
|
|
a86563cfb1 | ||
|
|
009882999f | ||
|
|
1da4fed9b5 | ||
|
|
6ee4b30ee9 | ||
|
|
4f9f21f661 | ||
|
|
527c3390f4 | ||
|
|
f9a488cd5a | ||
|
|
02bd322c1d | ||
|
|
a0acc6e913 | ||
|
|
0419aada6e | ||
|
|
6f442b6617 | ||
|
|
a0a5100807 | ||
|
|
a769fc4ff3 | ||
|
|
83cca343c3 | ||
|
|
bfcbb94aed | ||
|
|
5d928d5187 | ||
|
|
23fa6018a4 | ||
|
|
53eb9a5f14 | ||
|
|
443bfec035 | ||
|
|
8534ce5ec2 | ||
|
|
92bedbb881 | ||
|
|
7090604de7 | ||
|
|
7dd0a63b68 | ||
|
|
a4ecd9d73e | ||
|
|
e94b667e16 | ||
|
|
f6127df15d | ||
|
|
a8afb9bd3c | ||
|
|
86622662bf | ||
|
|
291fdd1894 | ||
|
|
46cef36184 | ||
|
|
bc449e10be | ||
|
|
d8703c223b | ||
|
|
28166c5bb1 | ||
|
|
54fdc572c1 | ||
|
|
6fb8fab665 | ||
|
|
df6b433066 | ||
|
|
26e30bf8e1 | ||
|
|
49d0ce1de4 | ||
|
|
d020e05f5b | ||
|
|
c346c57341 | ||
|
|
d237549496 | ||
|
|
607fef2d8f | ||
|
|
a50bf1c944 | ||
|
|
4ea0074548 | ||
|
|
4b46c73088 | ||
|
|
6fc32d9645 | ||
|
|
279ea25e7d | ||
|
|
50f17666fa | ||
|
|
b097840ba4 | ||
|
|
22ebd1c7a9 | ||
|
|
df764a3f3b | ||
|
|
5ccb499a6f | ||
|
|
b24ef60b33 | ||
|
|
6450126933 | ||
|
|
314a9e52e9 | ||
|
|
5d7bd37ab2 | ||
|
|
c96e71a3d7 | ||
|
|
e3f9581a69 | ||
|
|
1d89098f77 | ||
|
|
71b3aa9cca | ||
|
|
991bd0004a | ||
|
|
d3ff9600b5 | ||
|
|
df9850f5ca | ||
|
|
fa9677242c | ||
|
|
131b06fec3 | ||
|
|
8e2b5d7ce3 | ||
|
|
edaa1f7fcd | ||
|
|
30d56b7064 | ||
|
|
1ed793f000 | ||
|
|
ae9291f625 | ||
|
|
1ad6f4a1ce | ||
|
|
932abeb0e2 | ||
|
|
35a0f1b246 | ||
|
|
cb3af09ebd | ||
|
|
9fb413a126 | ||
|
|
27406c8daa | ||
|
|
f6129ebfee | ||
|
|
7f5fe8c877 | ||
|
|
07628dc05d | ||
|
|
78a29b5a87 | ||
|
|
6704f7bbb0 |
24
.gitignore
vendored
24
.gitignore
vendored
@@ -1,31 +1,9 @@
|
|||||||
*.log
|
*.log
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
nominatim/*.d
|
build
|
||||||
nominatim/*.o
|
|
||||||
nominatim/nominatim
|
|
||||||
module/nominatim.so
|
|
||||||
module/nominatim.o
|
|
||||||
settings/configuration.txt
|
|
||||||
settings/download.lock
|
|
||||||
settings/state.txt
|
|
||||||
settings/local.php
|
settings/local.php
|
||||||
|
|
||||||
.deps/
|
|
||||||
autom4te.cache/
|
|
||||||
config.*
|
|
||||||
configure
|
|
||||||
Makefile
|
|
||||||
!tests/scenes/bin/Makefile
|
|
||||||
Makefile.in
|
|
||||||
stamp-h1
|
|
||||||
missing
|
|
||||||
INSTALL
|
|
||||||
aclocal.m4
|
|
||||||
depcomp
|
|
||||||
install-sh
|
|
||||||
compile
|
|
||||||
|
|
||||||
data/wiki_import.sql
|
data/wiki_import.sql
|
||||||
data/wiki_specialphrases.sql
|
data/wiki_specialphrases.sql
|
||||||
data/osmosischange.osc
|
data/osmosischange.osc
|
||||||
|
|||||||
31
.travis.yml
Normal file
31
.travis.yml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
|
language: python
|
||||||
|
python:
|
||||||
|
- "3.6"
|
||||||
|
addons:
|
||||||
|
postgresql: "9.6"
|
||||||
|
git:
|
||||||
|
depth: 3
|
||||||
|
env:
|
||||||
|
- TEST_SUITE=tests
|
||||||
|
- TEST_SUITE=monaco
|
||||||
|
install:
|
||||||
|
- vagrant/install-on-travis-ci.sh
|
||||||
|
before_script:
|
||||||
|
- psql -U postgres -c "create extension postgis"
|
||||||
|
script:
|
||||||
|
- cd $TRAVIS_BUILD_DIR/build
|
||||||
|
- if [[ $TEST_SUITE == "monaco" ]]; then wget --no-verbose --output-document=../data/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf; fi
|
||||||
|
- if [[ $TEST_SUITE == "monaco" ]]; then ./utils/setup.php --osm-file ../data/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | grep -v 'ETA (seconds)'; fi
|
||||||
|
- if [[ $TEST_SUITE == "monaco" ]]; then ./utils/specialphrases.php --wiki-import | psql -d test_api_nominatim >/dev/null; fi
|
||||||
|
- cd $TRAVIS_BUILD_DIR/test/php
|
||||||
|
- if [[ $TEST_SUITE == "tests" ]]; then phpunit ./ ; fi
|
||||||
|
- if [[ $TEST_SUITE == "tests" ]]; then phpcs --report-width=120 */**.php ; fi
|
||||||
|
- cd $TRAVIS_BUILD_DIR/test/bdd
|
||||||
|
- # behave --format=progress3 api
|
||||||
|
- if [[ $TEST_SUITE == "tests" ]]; then behave --format=progress3 db ; fi
|
||||||
|
- if [[ $TEST_SUITE == "tests" ]]; then behave --format=progress3 osm2pgsql ; fi
|
||||||
|
notifications:
|
||||||
|
email: false
|
||||||
7
AUTHORS
7
AUTHORS
@@ -2,18 +2,17 @@ Nominatim was written by:
|
|||||||
|
|
||||||
Brian Quinion
|
Brian Quinion
|
||||||
Sarah Hoffmann
|
Sarah Hoffmann
|
||||||
|
Marc Tobias Metten
|
||||||
|
markigail
|
||||||
|
IrlJidel
|
||||||
Frederik Ramm
|
Frederik Ramm
|
||||||
Michael Spreng
|
Michael Spreng
|
||||||
Daniele Forsi
|
Daniele Forsi
|
||||||
mfn
|
mfn
|
||||||
Grant Slater
|
Grant Slater
|
||||||
Andree Klattenhoff
|
Andree Klattenhoff
|
||||||
IrlJidel
|
|
||||||
appelflap
|
appelflap
|
||||||
b3nn0
|
b3nn0
|
||||||
Spin0us
|
Spin0us
|
||||||
Kurt Roeckx
|
Kurt Roeckx
|
||||||
Rodolphe Quiédeville
|
Rodolphe Quiédeville
|
||||||
Marc Tobias Metten
|
|
||||||
|
|
||||||
Reverse geocoding using Tiger data feature made possible with support from Guru Labs
|
|
||||||
|
|||||||
150
CMakeLists.txt
Normal file
150
CMakeLists.txt
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# CMake Config
|
||||||
|
#
|
||||||
|
# Nominatim
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Project version
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
project(nominatim)
|
||||||
|
|
||||||
|
set(NOMINATIM_VERSION_MAJOR 3)
|
||||||
|
set(NOMINATIM_VERSION_MINOR 0)
|
||||||
|
|
||||||
|
set(NOMINATIM_VERSION "${NOMINATIM_VERSION_MAJOR}.${NOMINATIM_VERSION_MINOR}")
|
||||||
|
|
||||||
|
add_definitions(-DNOMINATIM_VERSION="${NOMINATIM_VERSION}")
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Find external dependencies
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(BUILD_TESTS off CACHE BOOL "Build test suite" FORCE)
|
||||||
|
set(WITH_LUA off CACHE BOOL "Build with lua support" FORCE)
|
||||||
|
|
||||||
|
if (NOT EXISTS "${CMAKE_SOURCE_DIR}/osm2pgsql/CMakeLists.txt")
|
||||||
|
message(FATAL_ERROR "The osm2pgsql directory is empty.\
|
||||||
|
Did you forget to check out Nominatim recursively?\
|
||||||
|
\nTry updating submodules with: git submodule update --init")
|
||||||
|
endif()
|
||||||
|
add_subdirectory(osm2pgsql)
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
unset(PostgreSQL_TYPE_INCLUDE_DIR CACHE)
|
||||||
|
set(PostgreSQL_TYPE_INCLUDE_DIR "/usr/include/")
|
||||||
|
find_package(PostgreSQL REQUIRED)
|
||||||
|
include_directories(${PostgreSQL_INCLUDE_DIRS})
|
||||||
|
link_directories(${PostgreSQL_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
find_program(PYOSMIUM pyosmium-get-changes)
|
||||||
|
if (NOT EXISTS "${PYOSMIUM}")
|
||||||
|
set(PYOSMIUM_PATH "/nonexistent")
|
||||||
|
message(WARNING "pyosmium-get-changes not found (required for updates)")
|
||||||
|
else()
|
||||||
|
set(PYOSMIUM_PATH "${PYOSMIUM}")
|
||||||
|
message(STATUS "Using pyosmium-get-changes at ${PYOSMIUM_PATH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
find_program(PG_CONFIG pg_config)
|
||||||
|
execute_process(COMMAND ${PG_CONFIG} --pgxs
|
||||||
|
OUTPUT_VARIABLE PGXS
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
|
if (NOT EXISTS "${PGXS}")
|
||||||
|
message(FATAL_ERROR "Postgresql server package not found.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
|
||||||
|
find_package(BZip2 REQUIRED)
|
||||||
|
|
||||||
|
find_package(LibXml2 REQUIRED)
|
||||||
|
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Setup settings and paths
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(CUSTOMFILES
|
||||||
|
settings/phrase_settings.php
|
||||||
|
website/deletable.php
|
||||||
|
website/details.php
|
||||||
|
website/hierarchy.php
|
||||||
|
website/lookup.php
|
||||||
|
website/polygons.php
|
||||||
|
website/reverse.php
|
||||||
|
website/search.php
|
||||||
|
website/status.php
|
||||||
|
utils/blocks.php
|
||||||
|
utils/country_languages.php
|
||||||
|
utils/imports.php
|
||||||
|
utils/importWikipedia.php
|
||||||
|
utils/query.php
|
||||||
|
utils/server_compare.php
|
||||||
|
utils/setup.php
|
||||||
|
utils/specialphrases.php
|
||||||
|
utils/update.php
|
||||||
|
utils/warm.php
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach (cfile ${CUSTOMFILES})
|
||||||
|
configure_file(${PROJECT_SOURCE_DIR}/${cfile} ${PROJECT_BINARY_DIR}/${cfile})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
configure_file(${PROJECT_SOURCE_DIR}/settings/defaults.php ${PROJECT_BINARY_DIR}/settings/settings.php)
|
||||||
|
|
||||||
|
set(WEBPATHS css images js)
|
||||||
|
|
||||||
|
foreach (wp ${WEBPATHS})
|
||||||
|
execute_process(
|
||||||
|
COMMAND ln -sf ${PROJECT_SOURCE_DIR}/website/${wp} ${PROJECT_BINARY_DIR}/website/
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Tests
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
|
set(TEST_BDD db osm2pgsql api)
|
||||||
|
|
||||||
|
foreach (test ${TEST_BDD})
|
||||||
|
add_test(NAME bdd_${test}
|
||||||
|
COMMAND lettuce features/${test}
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests)
|
||||||
|
set_tests_properties(bdd_${test}
|
||||||
|
PROPERTIES ENVIRONMENT "NOMINATIM_DIR=${PROJECT_BINARY_DIR}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_test(NAME php
|
||||||
|
COMMAND phpunit ./
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests-php)
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
add_subdirectory(module)
|
||||||
|
add_subdirectory(nominatim)
|
||||||
|
add_subdirectory(docs)
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
100
CONTRIBUTING.md
Normal file
100
CONTRIBUTING.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Nominatim contribution guidelines
|
||||||
|
|
||||||
|
## Reporting Bugs
|
||||||
|
|
||||||
|
Bugs can be reported at https://github.com/openstreetmap/Nominatim/issues.
|
||||||
|
Please always open a separate issue for each problem. In particular, do
|
||||||
|
not add your bugs to closed issues. They may looks similar to you but
|
||||||
|
often are completely different from the maintainer's point of view.
|
||||||
|
|
||||||
|
### When Reporting Bad Search Results...
|
||||||
|
|
||||||
|
Please make sure to add the following information:
|
||||||
|
|
||||||
|
* the URL of the query that produces the bad result
|
||||||
|
* the result you are getting
|
||||||
|
* the expected result, preferably a link to the OSM object you want to find,
|
||||||
|
otherwise an address that is as precise as possible
|
||||||
|
|
||||||
|
To get the link to the OSM object, you can try the following:
|
||||||
|
|
||||||
|
* go to https://openstreetmap.org
|
||||||
|
* zoom to the area of the map where you expect the result and
|
||||||
|
zoom in as much as possible
|
||||||
|
* click on the question mark on the right side of the map,
|
||||||
|
then with the queston cursor on the map where your object is located
|
||||||
|
* find the object of interest in the list that appears on the left side
|
||||||
|
* click on the object and report the URL back that the browser shows
|
||||||
|
|
||||||
|
### When Reporting Problems with your Installation...
|
||||||
|
|
||||||
|
Please add the following information to your issue:
|
||||||
|
|
||||||
|
* hardware configuration: RAM size, CPUs, kind and size of disks
|
||||||
|
* Operating system (also mention if you are running on a cloud service)
|
||||||
|
* Postgres and Postgis version
|
||||||
|
* list of settings you changed in your Postgres configuration
|
||||||
|
* Nominatim version (release version or,
|
||||||
|
if you run from the git repo, the output of `git rev-parse HEAD`)
|
||||||
|
* (if applicable) exact command line of the command that was causing the issue
|
||||||
|
|
||||||
|
|
||||||
|
## Workflow for Pull Requests
|
||||||
|
|
||||||
|
We love to get pull reuqests from you. We operate the "Fork & Pull" model
|
||||||
|
explained at
|
||||||
|
|
||||||
|
https://help.github.com/articles/using-pull-requests
|
||||||
|
|
||||||
|
You should fork the project into your own repo, create a topic branch
|
||||||
|
there and then make one or more pull requests back to the openstreetmap repository.
|
||||||
|
Your pull requests will then be reviewed and discussed. Please be aware
|
||||||
|
that you are responsible for your pull requests. You should be prepared
|
||||||
|
to get change requests because as the maintainers we have to make sure
|
||||||
|
that your contribution fits well with the rest of the code. Please make
|
||||||
|
sure that you have time to react to these comments and amend the code or
|
||||||
|
engage in a conversion. Do not expect that others will pick up your code,
|
||||||
|
it will almost never happen.
|
||||||
|
|
||||||
|
Please open a separate pull request for each issue you want to address.
|
||||||
|
Don't mix multiple changes. In particular, don't mix style cleanups with
|
||||||
|
feature pull requests. If you plan to make larger changes, please open
|
||||||
|
an issue first or comment on the appropriate issue already existing so
|
||||||
|
that duplicate work can be avoided.
|
||||||
|
|
||||||
|
## Coding style
|
||||||
|
|
||||||
|
Nominatim historically hasn't followed a particular coding style but we
|
||||||
|
are in process of consolodating the style. The following rules apply:
|
||||||
|
|
||||||
|
* Python code uses the official Python style
|
||||||
|
* indention
|
||||||
|
* SQL use 2 spaces
|
||||||
|
* all other file types use 4 spaces
|
||||||
|
* [BSD style](https://en.wikipedia.org/wiki/Indent_style#Allman_style) for braces
|
||||||
|
* spaces
|
||||||
|
* spaces before and after equal signs and operators
|
||||||
|
* no trailing spaces
|
||||||
|
* no spaces after opening and before closing bracket
|
||||||
|
* leave out space between a function name and bracket
|
||||||
|
but add one between control statement(if, while, etc.) and bracket
|
||||||
|
|
||||||
|
The coding style is enforced with PHPCS and can be tested with:
|
||||||
|
|
||||||
|
```
|
||||||
|
phpcs --report-width=120 --colors */**.php
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Before submitting a pull request make sure that the following tests pass:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd test/bdd
|
||||||
|
behave -DBUILDDIR=<builddir> db osm2pgsql
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
cd test/php
|
||||||
|
phpunit ./
|
||||||
|
```
|
||||||
31
ChangeLog
31
ChangeLog
@@ -1,3 +1,34 @@
|
|||||||
|
3.0
|
||||||
|
|
||||||
|
* move to cmake build system
|
||||||
|
* various fixes to HTML output
|
||||||
|
* reverse endpoint now can return geometries
|
||||||
|
* add support for PHP7
|
||||||
|
* move to on-the-fly computation of interpolations
|
||||||
|
* improve handling of linked places (updating)
|
||||||
|
* improve test framework:
|
||||||
|
* replace lettuce with behave
|
||||||
|
* use smaller database for API tests
|
||||||
|
* drop support for postgres < 9.1, postgis < 2.0 and PHP < 5.4
|
||||||
|
* make external data use optional (useful for imports without US)
|
||||||
|
* detect postgres and postgis versions automatically
|
||||||
|
* clean up query logging and remove unused tables
|
||||||
|
* move installation documentation into this repo
|
||||||
|
* add self-documenting vagrant scripts
|
||||||
|
* remove --create-website, recommend to use website directory in build
|
||||||
|
* add accessor functions for URL parameters and improve erro checking
|
||||||
|
* remove IP blocking and rate-limiting code
|
||||||
|
* enable CI via travis
|
||||||
|
* reformatting for more consistent coding style
|
||||||
|
* make country search term creation part of setup
|
||||||
|
* update country names and country grid
|
||||||
|
* handle roads that cross boundaries better
|
||||||
|
* keep full information on address tags
|
||||||
|
* update to refactored osm2pgsql which use libosmium based types
|
||||||
|
* switch from osmosis to pyosmium for updates
|
||||||
|
* be more strict when matching against special search terms
|
||||||
|
* handle postcode entries with mutliple values correctly
|
||||||
|
|
||||||
2.5
|
2.5
|
||||||
|
|
||||||
* reverse geocoding includes looking up housenumbers from Tiger data
|
* reverse geocoding includes looking up housenumbers from Tiger data
|
||||||
|
|||||||
27
Makefile.am
27
Makefile.am
@@ -1,27 +0,0 @@
|
|||||||
ACLOCAL_AMFLAGS = -I osm2pgsql/m4
|
|
||||||
AUTOMAKE_OPTIONS = -Wno-portability
|
|
||||||
|
|
||||||
SUBDIRS = osm2pgsql module nominatim
|
|
||||||
|
|
||||||
NOMINATIM_SERVER ?= $(shell echo a | php -F lib/init.php -E 'echo CONST_Website_BaseURL."\n";')
|
|
||||||
NOMINATIM_DATABASE ?= $(shell echo a | php -F lib/init.php -E 'echo DB::parseDSN(CONST_Database_DSN)["database"];')
|
|
||||||
|
|
||||||
install:
|
|
||||||
@echo Nominatim needs to be executed directly from this directory. No install necessary.
|
|
||||||
|
|
||||||
test:
|
|
||||||
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} lettuce -t -Fail -t -poldi-only
|
|
||||||
|
|
||||||
test-fast:
|
|
||||||
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} NOMINATIM_REUSE_TEMPLATE=1 lettuce -t -Fail -t -poldi-only
|
|
||||||
|
|
||||||
test-db:
|
|
||||||
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} lettuce -t -Fail -t -poldi-only features/db
|
|
||||||
|
|
||||||
test-db-fast:
|
|
||||||
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} NOMINATIM_REUSE_TEMPLATE=1 lettuce -t -Fail -t -poldi-only features/db
|
|
||||||
|
|
||||||
test-api:
|
|
||||||
cd tests; NOMINATIM_SERVER=${NOMINATIM_SERVER} lettuce -t -Fail -t -poldi-only features/api
|
|
||||||
|
|
||||||
.PHONY: test test-fast test-db test-db-fast test-api
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
[](https://travis-ci.org/openstreetmap/Nominatim)
|
||||||
|
|
||||||
Nominatim
|
Nominatim
|
||||||
=========
|
=========
|
||||||
|
|
||||||
@@ -12,37 +14,37 @@ Documentation
|
|||||||
=============
|
=============
|
||||||
|
|
||||||
More information about Nominatim, including usage and installation instructions,
|
More information about Nominatim, including usage and installation instructions,
|
||||||
can be found in the OSM wiki at:
|
can be found in the docs/ subdirectory and in the OSM wiki at:
|
||||||
|
|
||||||
http://wiki.openstreetmap.org/wiki/Nominatim
|
http://wiki.openstreetmap.org/wiki/Nominatim
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
The following instructions is a quick guide to installation. A more detailed guide
|
There are detailed installation instructions in the /docs directory.
|
||||||
how to set up your own instance of Nominatim can be found in the wiki:
|
Here is a quick summary of the necessary steps.
|
||||||
|
|
||||||
http://wiki.openstreetmap.org/wiki/Nominatim/Installation
|
|
||||||
|
|
||||||
Note that this repository contains a submodule called osm2pgsql. Make sure it
|
|
||||||
is cloned as well by running `git submodule update --init`.
|
|
||||||
|
|
||||||
Installation steps:
|
|
||||||
|
|
||||||
0. If checking out from git run:
|
|
||||||
|
|
||||||
./autogen.sh
|
|
||||||
|
|
||||||
1. Compile Nominatim:
|
1. Compile Nominatim:
|
||||||
|
|
||||||
./configure
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
make
|
make
|
||||||
|
|
||||||
|
For more detailed installation instructions see [docs/Installation.md](docs/Installation.md).
|
||||||
|
There are also step-by-step instructions for
|
||||||
|
[Ubuntu 16.04](docs/install-on-ubuntu-16.md) and
|
||||||
|
[CentOS 7.2](docs/install-on-centos-7.md).
|
||||||
|
|
||||||
2. Get OSM data and import:
|
2. Get OSM data and import:
|
||||||
|
|
||||||
./utils/setup.php --osm-file <your planet file> --all
|
./build/utils/setup.php --osm-file <your planet file> --all
|
||||||
|
|
||||||
|
Details can be found in [docs/Import_and_update.md](docs/Import_and_update.md)
|
||||||
|
|
||||||
|
3. Point your webserver to the ./build/website directory.
|
||||||
|
|
||||||
|
|
||||||
3. Point your webserver to the ./website directory.
|
|
||||||
|
|
||||||
License
|
License
|
||||||
=======
|
=======
|
||||||
@@ -56,4 +58,4 @@ For questions you can join the geocoding mailinglist, see
|
|||||||
http://lists.openstreetmap.org/listinfo/geocoding
|
http://lists.openstreetmap.org/listinfo/geocoding
|
||||||
|
|
||||||
Bugs may be reported on the github project site:
|
Bugs may be reported on the github project site:
|
||||||
https://github.com/twain47/Nominatim
|
https://github.com/openstreetmap/Nominatim
|
||||||
11
VAGRANT.md
11
VAGRANT.md
@@ -17,7 +17,7 @@ is.
|
|||||||
|
|
||||||
3. Nominatim
|
3. Nominatim
|
||||||
|
|
||||||
git clone --recursive https://github.com/twain47/Nominatim.git
|
git clone --recursive https://github.com/openstreetmap/Nominatim.git
|
||||||
|
|
||||||
If you haven't used `--recursive`, then you can load the submodules using
|
If you haven't used `--recursive`, then you can load the submodules using
|
||||||
|
|
||||||
@@ -45,11 +45,10 @@ is.
|
|||||||
|
|
||||||
```
|
```
|
||||||
# inside the virtual machine:
|
# inside the virtual machine:
|
||||||
cd Nominatim
|
mkdir data
|
||||||
wget --no-verbose --output-document=data/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf
|
cd build
|
||||||
./utils/setup.php --osm-file data/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | tee monaco.$$.log
|
wget --no-verbose --output-document=../data/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf
|
||||||
./utils/specialphrases.php --countries > data/specialphrases_countries.sql
|
./utils/setup.php --osm-file ../data/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | tee monaco.$$.log
|
||||||
psql -d nominatim -f data/specialphrases_countries.sql
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To repeat an import you'd need to delete the database first
|
To repeat an import you'd need to delete the database first
|
||||||
|
|||||||
34
Vagrantfile
vendored
34
Vagrantfile
vendored
@@ -3,20 +3,42 @@
|
|||||||
|
|
||||||
Vagrant.configure("2") do |config|
|
Vagrant.configure("2") do |config|
|
||||||
# Apache webserver
|
# Apache webserver
|
||||||
config.vm.network "forwarded_port", guest: 8089, host: 8089
|
config.vm.network "forwarded_port", guest: 80, host: 8089
|
||||||
|
|
||||||
# If true, then any SSH connections made will enable agent forwarding.
|
# If true, then any SSH connections made will enable agent forwarding.
|
||||||
config.ssh.forward_agent = true
|
config.ssh.forward_agent = true
|
||||||
|
|
||||||
|
checkout = "yes"
|
||||||
|
if ENV['CHECKOUT'] != 'y' then
|
||||||
config.vm.synced_folder ".", "/home/vagrant/Nominatim"
|
config.vm.synced_folder ".", "/home/vagrant/Nominatim"
|
||||||
|
checkout = "no"
|
||||||
config.vm.define "ubuntu" do |sub|
|
|
||||||
sub.vm.box = "ubuntu/trusty64"
|
|
||||||
sub.vm.provision :shell, :path => "vagrant/ubuntu-trusty-provision.sh"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config.vm.define "ubuntu", primary: true do |sub|
|
||||||
|
sub.vm.box = "bento/ubuntu-16.04"
|
||||||
|
sub.vm.provision :shell do |s|
|
||||||
|
s.path = "vagrant/Install-on-Ubuntu-16.sh"
|
||||||
|
s.privileged = false
|
||||||
|
s.args = [checkout]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
config.vm.define "travis" do |sub|
|
||||||
|
sub.vm.box = "bento/ubuntu-14.04"
|
||||||
|
sub.vm.provision :shell do |s|
|
||||||
|
s.path = "vagrant/install-on-travis-ci.sh"
|
||||||
|
s.privileged = false
|
||||||
|
s.args = [checkout]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
config.vm.define "centos" do |sub|
|
config.vm.define "centos" do |sub|
|
||||||
sub.vm.box = "bento/centos-7.2"
|
sub.vm.box = "bento/centos-7.2"
|
||||||
sub.vm.provision :shell, :path => "vagrant/centos-7-provision.sh"
|
sub.vm.provision :shell do |s|
|
||||||
|
s.path = "vagrant/Install-on-Centos-7.sh"
|
||||||
|
s.privileged = false
|
||||||
|
s.args = [checkout]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# configure shared package cache if possible
|
# configure shared package cache if possible
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
autoreconf -vfi
|
|
||||||
67
configure.ac
67
configure.ac
@@ -1,67 +0,0 @@
|
|||||||
AC_INIT(Nominatim,2.5)
|
|
||||||
if git rev-parse HEAD 2>/dev/null >/dev/null; then
|
|
||||||
AC_SUBST([PACKAGE_VERSION], [$PACKAGE_VERSION-git-`git rev-parse --short HEAD`])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl Required autoconf version
|
|
||||||
AC_PREREQ(2.61)
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([1.9.6 dist-bzip2 std-options check-news])
|
|
||||||
|
|
||||||
dnl Additional macro definitions are in here
|
|
||||||
m4_include([m4/ax_lib_postgresql_svr.m4])
|
|
||||||
AC_CONFIG_MACRO_DIR([osm2pgsql/m4])
|
|
||||||
|
|
||||||
dnl Generate configuration header file
|
|
||||||
AC_CONFIG_HEADER(nominatim/config.h)
|
|
||||||
|
|
||||||
|
|
||||||
dnl Find C compiler
|
|
||||||
AC_PROG_CC
|
|
||||||
|
|
||||||
dnl Find C++ compiler
|
|
||||||
AC_PROG_CXX
|
|
||||||
|
|
||||||
dnl pthread
|
|
||||||
AX_PTHREAD([], [AC_MSG_ERROR([pthread library required])])
|
|
||||||
|
|
||||||
dnl Check for Geos library
|
|
||||||
AX_LIB_GEOS
|
|
||||||
if test "x$GEOS_VERSION" = "x"
|
|
||||||
then
|
|
||||||
AC_MSG_ERROR([required library not found]);
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl Check for Proj library
|
|
||||||
AX_LIB_PROJ
|
|
||||||
if test "$HAVE_PROJ" = "no"
|
|
||||||
then
|
|
||||||
AC_MSG_ERROR([required library not found]);
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
dnl Check for PostgresSQL client library
|
|
||||||
AX_LIB_POSTGRESQL(9.0)
|
|
||||||
if test "x$POSTGRESQL_VERSION" = "x"
|
|
||||||
then
|
|
||||||
AC_MSG_ERROR([postgresql client library not found])
|
|
||||||
fi
|
|
||||||
AX_LIB_POSTGRESQL_SVR(9.0)
|
|
||||||
if test ! -f "$POSTGRESQL_PGXS"
|
|
||||||
then
|
|
||||||
AC_MSG_ERROR([postgresql server development library not found])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl Check for bzip2 library
|
|
||||||
AX_LIB_BZIP2
|
|
||||||
if test "$HAVE_BZIP2" = "no"
|
|
||||||
then
|
|
||||||
AC_MSG_ERROR([required library not found]);
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl Check for libxml2 library
|
|
||||||
AM_PATH_XML2
|
|
||||||
|
|
||||||
AC_CONFIG_SUBDIRS([osm2pgsql])
|
|
||||||
|
|
||||||
AC_OUTPUT(Makefile nominatim/Makefile module/Makefile)
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# This file includes a small subset of OpenLayers code, designed to be
|
|
||||||
# integrated into another application. It includes only the Layer types
|
|
||||||
# neccesary to create tiled or untiled WMS, and does not include any Controls.
|
|
||||||
# This is the result of what was at the time called "Webmap.js" at the FOSS4G
|
|
||||||
# Web Mapping BOF.
|
|
||||||
|
|
||||||
[first]
|
|
||||||
|
|
||||||
[last]
|
|
||||||
|
|
||||||
[include]
|
|
||||||
OpenLayers/Map.js
|
|
||||||
OpenLayers/Kinetic.js
|
|
||||||
OpenLayers/Geometry/MultiLineString.js
|
|
||||||
OpenLayers/Geometry/MultiPolygon.js
|
|
||||||
OpenLayers/Format/WKT.js
|
|
||||||
OpenLayers/Layer/OSM.js
|
|
||||||
OpenLayers/Layer/Vector.js
|
|
||||||
OpenLayers/Layer/SphericalMercator.js
|
|
||||||
OpenLayers/Control/Attribution.js
|
|
||||||
OpenLayers/Control/KeyboardDefaults.js
|
|
||||||
OpenLayers/Control/Navigation.js
|
|
||||||
OpenLayers/Control/MousePosition.js
|
|
||||||
OpenLayers/Control/PanZoomBar.js
|
|
||||||
OpenLayers/Control/Permalink.js
|
|
||||||
OpenLayers/Control/TouchNavigation.js
|
|
||||||
OpenLayers/Style.js
|
|
||||||
OpenLayers/Protocol/HTTP.js
|
|
||||||
OpenLayers/Projection.js
|
|
||||||
OpenLayers/Renderer/SVG.js
|
|
||||||
OpenLayers/Renderer/VML.js
|
|
||||||
OpenLayers/Renderer/Canvas.js
|
|
||||||
|
|
||||||
[exclude]
|
|
||||||
|
|
||||||
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -18316,7 +18316,6 @@ COPY us_postcode (postcode, x, y) FROM stdin;
|
|||||||
45682 -82.7132476732882651 38.8141238738390513
|
45682 -82.7132476732882651 38.8141238738390513
|
||||||
32822 -81.2890641417997699 28.4996104146691565
|
32822 -81.2890641417997699 28.4996104146691565
|
||||||
10589 -73.6946260932133725 41.3319987693007462
|
10589 -73.6946260932133725 41.3319987693007462
|
||||||
-110.390038309796751 39.5043862981486527
|
|
||||||
95253 -121.205984758554834 38.1383772536563157
|
95253 -121.205984758554834 38.1383772536563157
|
||||||
44168 -83.5412335555174792 42.4016783877205441
|
44168 -83.5412335555174792 42.4016783877205441
|
||||||
38870 -88.3578842735458778 34.0629206861111911
|
38870 -88.3578842735458778 34.0629206861111911
|
||||||
|
|||||||
2930
data/us_state.sql
2930
data/us_state.sql
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
79347
data/words.sql
79347
data/words.sql
File diff suppressed because it is too large
Load Diff
32
docs/CMakeLists.txt
Normal file
32
docs/CMakeLists.txt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Auto-generated vagrant install documentation
|
||||||
|
|
||||||
|
set (INSTALLDOCFILES
|
||||||
|
Install-on-Centos-7
|
||||||
|
Install-on-Ubuntu-16
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach (df ${INSTALLDOCFILES})
|
||||||
|
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${df}.md
|
||||||
|
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bash2md.sh ${PROJECT_SOURCE_DIR}/vagrant/${df}.sh ${CMAKE_CURRENT_BINARY_DIR}/${df}.md
|
||||||
|
MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/vagrant/${df}.sh
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bash2md.sh
|
||||||
|
COMMENT "Creating markdown docs from vagrant/${df}.sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_CUSTOM_TARGET( md_install_${df} ALL
|
||||||
|
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${df}.md
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Copied static documentation
|
||||||
|
|
||||||
|
set (GENERALDOCFILES
|
||||||
|
Installation.md
|
||||||
|
Import-and-Update.md
|
||||||
|
Faq.md
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach (df ${GENERALDOCFILES})
|
||||||
|
CONFIGURE_FILE(${df} ${df})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
127
docs/Faq.md
Normal file
127
docs/Faq.md
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
Frequently Asked Questions
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Running Your Own Instance
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
### Can I import only a few countries and also keep them up to date?
|
||||||
|
|
||||||
|
You should use the extracts and updates from http://download.geofabrik.de.
|
||||||
|
For the intial import, download the countries you need and merge them.
|
||||||
|
See [OSM Help](https://help.openstreetmap.org/questions/48843/merging-two-or-more-geographical-areas-to-import-two-or-more-osm-files-in-nominatim)
|
||||||
|
for examples how to do that. Use the resulting single osm file when
|
||||||
|
running `setup.php`.
|
||||||
|
|
||||||
|
For updates you need to download the change files for each country
|
||||||
|
once per day and apply them **separately** using
|
||||||
|
|
||||||
|
./utils/update.php --import-diff <filename> --index
|
||||||
|
|
||||||
|
See [this issue](https://github.com/openstreetmap/Nominatim/issues/60#issuecomment-18679446)
|
||||||
|
for a script that runs the updates using osmosis.
|
||||||
|
|
||||||
|
### My website shows: `XML Parsing Error: XML or text declaration not at start of entity Location</code>.`
|
||||||
|
|
||||||
|
Make sure there are no spaces at the beginning of your `settings/local.php` file.
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
### I accidentally killed the import process after it has been running for many hours. Can it be resumed?
|
||||||
|
|
||||||
|
It is possible if the import already got to the indexing stage.
|
||||||
|
Check the last line of output that was logged before the process
|
||||||
|
was killed. If it looks like this:
|
||||||
|
|
||||||
|
Done 844 in 13 @ 64.923080 per second - Rank 26 ETA (seconds): 7.886255
|
||||||
|
|
||||||
|
then you can resume with the following command:
|
||||||
|
|
||||||
|
./utils/setup.php --index --create-search-indices --create-country-names
|
||||||
|
|
||||||
|
If the reported rank is 26 or higher, you can also safely add `-index-noanalyse`.
|
||||||
|
|
||||||
|
|
||||||
|
### When running the setup.php script I get a warning:
|
||||||
|
`PHP Warning: file_get_contents(): open_basedir restriction in effect.`
|
||||||
|
|
||||||
|
You need to adjust the [open_basedir](http://www.php.net/manual/en/ini.core.php#ini.open-basedir) setting
|
||||||
|
in your PHP configuration (php.ini file). By default this setting may look like this:
|
||||||
|
|
||||||
|
open_basedir = /srv/http/:/home/:/tmp/:/usr/share/pear/
|
||||||
|
|
||||||
|
Either add reported directories to the list or disable this setting temporarily by
|
||||||
|
dding ";" at the beginning of the line. Don't forget to enable this setting again
|
||||||
|
once you are done with the PHP command line operations.
|
||||||
|
|
||||||
|
|
||||||
|
### The Apache log contains lots of PHP warnings like this:
|
||||||
|
`PHP Warning: date_default_timezone_set() function.`
|
||||||
|
|
||||||
|
You should set the default time zone as instructed in the warning in
|
||||||
|
your `php.ini` file. Find the entry about timezone and set it to
|
||||||
|
something like this:
|
||||||
|
|
||||||
|
; Defines the default timezone used by the date functions
|
||||||
|
; http://php.net/date.timezone
|
||||||
|
date.timezone = 'America/Denver'
|
||||||
|
|
||||||
|
Or
|
||||||
|
|
||||||
|
echo "date.timezone = 'America/Denver'" > /etc/php.d/timezone.ini
|
||||||
|
|
||||||
|
|
||||||
|
### When running the import I get a version mismatch:
|
||||||
|
`COPY_END for place failed: ERROR: incompatible library "/opt/Nominatim/module/nominatim.so": version mismatch`
|
||||||
|
|
||||||
|
pg_config seems to use bad includes sometimes when multiple versions
|
||||||
|
of PostgreSQL are available in the system. Make sure you remove the
|
||||||
|
server development libraries (`postgresql-server-dev-9.1` on Ubuntu)
|
||||||
|
and recompile (`cmake .. && make`).
|
||||||
|
|
||||||
|
|
||||||
|
### I see the error: `function transliteration(text) does not exist`
|
||||||
|
|
||||||
|
Reinstall the nominatim functions with `setup.php --create--functions`
|
||||||
|
and check for any errors, e.g. a missing `nominatim.so` file.
|
||||||
|
|
||||||
|
|
||||||
|
### The website shows: `Could not get word tokens`
|
||||||
|
|
||||||
|
The server cannot access your database. Add `&debug=1` to your URL
|
||||||
|
to get the full error message.
|
||||||
|
|
||||||
|
|
||||||
|
### On CentOS the website shows `could not connect to server: No such file or directory`
|
||||||
|
|
||||||
|
On CentOS v7 the PostgreSQL server is started with `systemd`.
|
||||||
|
Check if `/usr/lib/systemd/system/httpd.service` contains a line `PrivateTmp=true`.
|
||||||
|
If so then Apache cannot see the `/tmp/.s.PGSQL.5432` file. It's a good security feature,
|
||||||
|
so use the [[#PostgreSQL_UNIX_Socket_Location_on_CentOS|preferred solution]]
|
||||||
|
|
||||||
|
However, you can solve this the quick and dirty way by commenting out that line and then run
|
||||||
|
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl restart httpd
|
||||||
|
|
||||||
|
|
||||||
|
### Setup.php fails with the message: `DB Error: extension not found`
|
||||||
|
|
||||||
|
Make sure you have the Postgres extensions hstore and postgis installed.
|
||||||
|
See the installation instruction for a full list of required packages.
|
||||||
|
|
||||||
|
### When running the setup.php script I get a error:
|
||||||
|
`Cannot redeclare getDB() (previously declared in /your/path/Nominatim/lib/db.php:4)`
|
||||||
|
|
||||||
|
The message is a bit misleading as PHP needs to load the file `DB.php` and
|
||||||
|
instead re-loads Nominatim's `db.php`. To solve this make sure you
|
||||||
|
have the [http://pear.php.net/package/DB/ Pear module 'DB'] installed.
|
||||||
|
|
||||||
|
sudo pear install DB
|
||||||
|
|
||||||
|
### I forgot to delete the flatnodes file before starting an import
|
||||||
|
|
||||||
|
That's fine. For each import the flatnodes file get overwritten.
|
||||||
|
See https://help.openstreetmap.org/questions/52419/nominatim-flatnode-storage
|
||||||
|
for more information.
|
||||||
177
docs/Import-and-Update.md
Normal file
177
docs/Import-and-Update.md
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
Importing a new database
|
||||||
|
========================
|
||||||
|
|
||||||
|
The following instructions explain how to create a Nominatim database
|
||||||
|
from an OSM planet file and how to keep the database up to date. It
|
||||||
|
is assumed that you have already successfully installed the Nominatim
|
||||||
|
software itself, if not return to the [installation page](Installation.md).
|
||||||
|
|
||||||
|
Configuration setup in settings/local.php
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
There are lots of configuration settings you can tweak. Have a look
|
||||||
|
at `settings/settings.php` for a full list. Most should have a sensible default.
|
||||||
|
If you plan to import a large dataset (e.g. Europe, North America, planet),
|
||||||
|
you should also enable flatnode storage of node locations. With this
|
||||||
|
setting enabled, node coordinates are stored in a simple file instead
|
||||||
|
of the database. This will save you import time and disk storage.
|
||||||
|
Add to your `settings/local.php`:
|
||||||
|
|
||||||
|
@define('CONST_Osm2pgsql_Flatnode_File', '/path/to/flatnode.file');
|
||||||
|
|
||||||
|
Replace the second part with a suitable path on your system and make sure
|
||||||
|
the directory exists. There should be at least 35GB of free space.
|
||||||
|
|
||||||
|
Downloading additional data
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
### Wikipedia rankings
|
||||||
|
|
||||||
|
Wikipedia can be used as an optional auxiliary data source to help indicate
|
||||||
|
the importance of osm features. Nominatim will work without this information
|
||||||
|
but it will improve the quality of the results if this is installed.
|
||||||
|
This data is available as a binary download:
|
||||||
|
|
||||||
|
cd $NOMINATIM_SOURCE_DIR/data
|
||||||
|
wget http://www.nominatim.org/data/wikipedia_article.sql.bin
|
||||||
|
wget http://www.nominatim.org/data/wikipedia_redirect.sql.bin
|
||||||
|
|
||||||
|
Combined the 2 files are around 1.5GB and add around 30GB to the install
|
||||||
|
size of nominatim. They also increase the install time by an hour or so.
|
||||||
|
|
||||||
|
### UK postcodes
|
||||||
|
|
||||||
|
Nominatim can use postcodes from an external source to improve searches that involve a UK postcode. This data can be optionally downloaded:
|
||||||
|
|
||||||
|
cd $NOMINATIM_SOURCE_DIR/data
|
||||||
|
wget http://www.nominatim.org/data/gb_postcode_data.sql.gz
|
||||||
|
|
||||||
|
|
||||||
|
Initial import of the data
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
**Important:** first try the import with a small excerpt, for example from
|
||||||
|
[Geofabrik](http://download.geofabrik.de).
|
||||||
|
|
||||||
|
Download the data to import and load the data with the following command:
|
||||||
|
|
||||||
|
./utils/setup.php --osm-file <your data file> --all [--osm2pgsql-cache 28000] 2>&1 | tee setup.log
|
||||||
|
|
||||||
|
The `--osm2pgsql-cache` parameter is optional but strongly recommended for
|
||||||
|
planet imports. It sets the node cache size for the osm2pgsql import part
|
||||||
|
(see `-C` parameter in osm2pgsql help). 28GB are recommended for a full planet
|
||||||
|
import, for excerpts you can use less. Adapt to your available RAM to
|
||||||
|
avoid swapping, never give more than 2/3 of RAM to osm2pgsql.
|
||||||
|
|
||||||
|
|
||||||
|
Loading additional datasets
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The following commands will create additional entries for POI searches:
|
||||||
|
|
||||||
|
./utils/specialphrases.php --wiki-import > specialphrases.sql
|
||||||
|
psql -d nominatim -f specialphrases.sql
|
||||||
|
|
||||||
|
|
||||||
|
Installing Tiger housenumber data for the US
|
||||||
|
============================================
|
||||||
|
|
||||||
|
Nominatim is able to use the official TIGER address set to complement the
|
||||||
|
OSM housenumber data in the US. You can add TIGER data to your own Nominatim
|
||||||
|
instance by following these steps:
|
||||||
|
|
||||||
|
1. Install the GDAL library and python bindings and the unzip tool
|
||||||
|
|
||||||
|
* Ubuntu: `sudo apt-get install python-gdal unzip`
|
||||||
|
* CentOS: `sudo yum install gdal-python unzip`
|
||||||
|
|
||||||
|
2. Get the TIGER 2015 data. You will need the EDGES files
|
||||||
|
(3,234 zip files, 11GB total). Choose one of the two sources:
|
||||||
|
|
||||||
|
wget -r ftp://ftp2.census.gov/geo/tiger/TIGER2015/EDGES/
|
||||||
|
wget -r ftp://mirror1.shellbot.com/census/geo/tiger/TIGER2015/EDGES/
|
||||||
|
|
||||||
|
The first one is the original source, the second a considerably faster
|
||||||
|
mirror.
|
||||||
|
|
||||||
|
3. Convert the data into SQL statements (stored in data/tiger):
|
||||||
|
|
||||||
|
./utils/imports.php --parse-tiger <tiger edge data directory>
|
||||||
|
|
||||||
|
4. Import the data into your Nominatim database:
|
||||||
|
|
||||||
|
./utils/setup.php --import-tiger-data
|
||||||
|
|
||||||
|
5. Enable use of the Tiger data in your `settings/local.php` by adding:
|
||||||
|
|
||||||
|
@define('CONST_Use_US_Tiger_Data', true);
|
||||||
|
|
||||||
|
6. Apply the new settings:
|
||||||
|
|
||||||
|
./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
|
||||||
|
|
||||||
|
Be warned that the import can take a very long time, especially if you
|
||||||
|
import all of the US. The entire US adds about 10GB to your database.
|
||||||
|
|
||||||
|
|
||||||
|
Updates
|
||||||
|
=======
|
||||||
|
|
||||||
|
There are many different possibilities to update your Nominatim database.
|
||||||
|
The following section describes how to keep it up-to-date with Pyosmium.
|
||||||
|
For a list of other methods see the output of `./utils/update.php --help`.
|
||||||
|
|
||||||
|
Installing the newest version of Pyosmium
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
It is recommended to install Pyosmium via pip:
|
||||||
|
|
||||||
|
pip install --user osmium
|
||||||
|
|
||||||
|
Nominatim needs a tool called `pyosmium-get-updates` that comes with
|
||||||
|
Pyosmium. You need to tell Nominatim where to find it. Add the
|
||||||
|
following line to your `settings/local.php`:
|
||||||
|
|
||||||
|
@define('CONST_Pyosmium_Binary', '/home/user/.local/bin/pyosmium-get-changes');
|
||||||
|
|
||||||
|
The path above is fine if you used the `--user` parameter with pip.
|
||||||
|
Replace `user` with your user name.
|
||||||
|
|
||||||
|
Setting up the update process
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Next the update needs to be initialised. By default Nominatim is configured
|
||||||
|
to update using the global minutely diffs.
|
||||||
|
|
||||||
|
If you want a different update source you will need to add some settings
|
||||||
|
to `settings/local.php`. For example, to use the daily country extracts
|
||||||
|
diffs for Ireland from geofabrik add the following:
|
||||||
|
|
||||||
|
// base URL of the replication service
|
||||||
|
@define('CONST_Replication_Url', 'http://download.geofabrik.de/europe/ireland-and-northern-ireland-updates');
|
||||||
|
// How often upstream publishes diffs
|
||||||
|
@define('CONST_Replication_Update_Interval', '86400');
|
||||||
|
// How long to sleep if no update found yet
|
||||||
|
@define('CONST_Replication_Recheck_Interval', '900');
|
||||||
|
|
||||||
|
To set up the update process now run the following command:
|
||||||
|
|
||||||
|
./utils/update --init-updates
|
||||||
|
|
||||||
|
It outputs the date where updates will start. Recheck that this date is
|
||||||
|
what you expect.
|
||||||
|
|
||||||
|
The --init-updates command needs to be rerun whenever the replication service
|
||||||
|
is changed.
|
||||||
|
|
||||||
|
Updating Nominatim
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The following command will keep your database constantly up to date:
|
||||||
|
|
||||||
|
./utils/update.php --import-osmosis-all
|
||||||
|
|
||||||
|
If you have imported multiple country extracts and want to keep them
|
||||||
|
up-to-date, have a look at the script in
|
||||||
|
[issue #60](https://github.com/openstreetmap/Nominatim/issues/60).
|
||||||
|
|
||||||
181
docs/Install-on-Centos-7.md
Normal file
181
docs/Install-on-Centos-7.md
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
|
||||||
|
*Note:* these installation instructions are also available in executable
|
||||||
|
form for use with vagrant under `vagrant/Install-on-Centos-7.sh`.
|
||||||
|
|
||||||
|
Installing the Required Software
|
||||||
|
================================
|
||||||
|
|
||||||
|
These instructions expect that you have a freshly installed CentOS version 7.
|
||||||
|
Make sure all packages are up-to-date by running:
|
||||||
|
|
||||||
|
sudo yum update -y
|
||||||
|
|
||||||
|
The standard CentOS repositories don't contain all the required packages,
|
||||||
|
you need to enable the EPEL repository as well. To enable it on CentOS,
|
||||||
|
install the epel-release RPM by running:
|
||||||
|
|
||||||
|
sudo yum install -y epel-release
|
||||||
|
|
||||||
|
Now you can install all packages needed for Nominatim:
|
||||||
|
|
||||||
|
sudo yum install -y postgresql-server postgresql-contrib postgresql-devel postgis postgis-utils \
|
||||||
|
git cmake make gcc gcc-c++ libtool policycoreutils-python \
|
||||||
|
php-pgsql php php-pear php-pear-DB php-intl libpqxx-devel proj-epsg \
|
||||||
|
bzip2-devel proj-devel geos-devel libxml2-devel boost-devel expat-devel zlib-devel
|
||||||
|
|
||||||
|
If you want to run the test suite, you need to install the following
|
||||||
|
additional packages:
|
||||||
|
|
||||||
|
sudo yum install -y python-pip python-Levenshtein python-psycopg2 \
|
||||||
|
python-numpy php-phpunit-PHPUnit
|
||||||
|
pip install --user --upgrade pip setuptools lettuce==0.2.18 six==1.9 \
|
||||||
|
haversine Shapely pytidylib
|
||||||
|
sudo pear install PHP_CodeSniffer
|
||||||
|
|
||||||
|
|
||||||
|
System Configuration
|
||||||
|
====================
|
||||||
|
|
||||||
|
The following steps are meant to configure a fresh CentOS installation
|
||||||
|
for use with Nominatim. You may skip some of the steps if you have your
|
||||||
|
OS already configured.
|
||||||
|
|
||||||
|
Creating Dedicated User Accounts
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Nominatim will run as a global service on your machine. It is therefore
|
||||||
|
best to install it under its own separate user account. In the following
|
||||||
|
we assume this user is called nominatim and the installation will be in
|
||||||
|
/srv/nominatim. To create the user and directory run:
|
||||||
|
|
||||||
|
sudo useradd -d /srv/nominatim -s /bin/bash -m nominatim
|
||||||
|
|
||||||
|
You may find a more suitable location if you wish.
|
||||||
|
|
||||||
|
To be able to copy and paste instructions from this manual, export
|
||||||
|
user name and home directory now like this:
|
||||||
|
|
||||||
|
export USERNAME=nominatim
|
||||||
|
export USERHOME=/srv/nominatim
|
||||||
|
|
||||||
|
**Never, ever run the installation as a root user.** You have been warned.
|
||||||
|
|
||||||
|
Make sure that system servers can read from the home directory:
|
||||||
|
|
||||||
|
chmod a+x $USERHOME
|
||||||
|
|
||||||
|
Setting up PostgreSQL
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
CentOS does not automatically create a database cluster. Therefore, start
|
||||||
|
with initializing the database, then enable the server to start at boot:
|
||||||
|
|
||||||
|
sudo postgresql-setup initdb
|
||||||
|
sudo systemctl enable postgresql
|
||||||
|
|
||||||
|
|
||||||
|
Next tune the postgresql configuration, which is located in
|
||||||
|
`/var/lib/pgsql/data/postgresql.conf`. See section *Postgres Tuning* in
|
||||||
|
[the installation page](Installation.md) for the parameters to change.
|
||||||
|
|
||||||
|
Now start the postgresql service after updating this config file.
|
||||||
|
|
||||||
|
sudo systemctl restart postgresql
|
||||||
|
|
||||||
|
|
||||||
|
Finally, we need to add two postgres users: one for the user that does
|
||||||
|
the import and another for the webserver which should access the database
|
||||||
|
only for reading:
|
||||||
|
|
||||||
|
|
||||||
|
sudo -u postgres createuser -s $USERNAME
|
||||||
|
sudo -u postgres createuser apache
|
||||||
|
|
||||||
|
|
||||||
|
Setting up the Apache Webserver
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
You need to create an alias to the website directory in your apache
|
||||||
|
configuration. Add a separate nominatim configuration to your webserver:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo tee /etc/httpd/conf.d/nominatim.conf << EOFAPACHECONF
|
||||||
|
<Directory "$USERHOME/Nominatim/build/website">
|
||||||
|
Options FollowSymLinks MultiViews
|
||||||
|
AddType text/html .php
|
||||||
|
DirectoryIndex search.php
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
Alias /nominatim $USERHOME/Nominatim/build/website
|
||||||
|
EOFAPACHECONF
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Then reload apache
|
||||||
|
|
||||||
|
|
||||||
|
sudo systemctl restart httpd
|
||||||
|
|
||||||
|
|
||||||
|
Adding SELinux Security Settings
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
It is a good idea to leave SELinux enabled and enforcing, particularly
|
||||||
|
with a web server accessible from the Internet. At a minimum the
|
||||||
|
following SELinux labeling should be done for Nominatim:
|
||||||
|
|
||||||
|
sudo semanage fcontext -a -t httpd_sys_content_t "$USERHOME/Nominatim/(website|lib|settings)(/.*)?"
|
||||||
|
sudo semanage fcontext -a -t lib_t "$USERHOME/Nominatim/module/nominatim.so"
|
||||||
|
sudo restorecon -R -v $USERHOME/Nominatim
|
||||||
|
|
||||||
|
|
||||||
|
Installing Nominatim
|
||||||
|
====================
|
||||||
|
|
||||||
|
Building and Configuration
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Get the source code from Github and change into the source directory
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cd $USERHOME
|
||||||
|
git clone --recursive git://github.com/openstreetmap/Nominatim.git
|
||||||
|
cd Nominatim
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
When installing the latest source from github, you also need to
|
||||||
|
download the country grid:
|
||||||
|
|
||||||
|
|
||||||
|
wget -O data/country_osm_grid.sql.gz http://www.nominatim.org/data/country_grid.sql.gz
|
||||||
|
|
||||||
|
|
||||||
|
The code must be built in a separate directory. Create this directory,
|
||||||
|
then configure and build Nominatim in there:
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake $USERHOME/Nominatim
|
||||||
|
make
|
||||||
|
|
||||||
|
You need to create a minimal configuration file that tells nominatim
|
||||||
|
the name of your webserver user and the URL of the website:
|
||||||
|
|
||||||
|
```
|
||||||
|
tee settings/local.php << EOF
|
||||||
|
<?php
|
||||||
|
@define('CONST_Database_Web_User', 'apache');
|
||||||
|
@define('CONST_Website_BaseURL', '/nominatim/');
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Nominatim is now ready to use. Continue with
|
||||||
|
[importing a database from OSM data](Import-and-Update.md).
|
||||||
167
docs/Install-on-Ubuntu-16.md
Normal file
167
docs/Install-on-Ubuntu-16.md
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*Note:* these installation instructions are also available in executable
|
||||||
|
form for use with vagrant under vagrant/Install-on-Ubuntu-16.sh.
|
||||||
|
|
||||||
|
Installing the Required Software
|
||||||
|
================================
|
||||||
|
|
||||||
|
These instructions expect that you have a freshly installed Ubuntu 16.04.
|
||||||
|
|
||||||
|
Make sure all packages are are up-to-date by running:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sudo apt-get update -qq
|
||||||
|
|
||||||
|
Now you can install all packages needed for Nominatim:
|
||||||
|
|
||||||
|
sudo apt-get install -y build-essential cmake g++ libboost-dev libboost-system-dev \
|
||||||
|
libboost-filesystem-dev libexpat1-dev zlib1g-dev libxml2-dev\
|
||||||
|
libbz2-dev libpq-dev libgeos-dev libgeos++-dev libproj-dev \
|
||||||
|
postgresql-server-dev-9.5 postgresql-9.5-postgis-2.2 postgresql-contrib-9.5 \
|
||||||
|
apache2 php php-pgsql libapache2-mod-php php-pear php-db \
|
||||||
|
php-intl git
|
||||||
|
|
||||||
|
If you want to run the test suite, you need to install the following
|
||||||
|
additional packages:
|
||||||
|
|
||||||
|
sudo apt-get install -y python3-dev python3-pip python3-psycopg2 python3-tidylib phpunit
|
||||||
|
|
||||||
|
pip3 install --user behave nose # urllib3
|
||||||
|
sudo pear install PHP_CodeSniffer
|
||||||
|
|
||||||
|
|
||||||
|
System Configuration
|
||||||
|
====================
|
||||||
|
|
||||||
|
The following steps are meant to configure a fresh Ubuntu installation
|
||||||
|
for use with Nominatim. You may skip some of the steps if you have your
|
||||||
|
OS already configured.
|
||||||
|
|
||||||
|
Creating Dedicated User Accounts
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Nominatim will run as a global service on your machine. It is therefore
|
||||||
|
best to install it under its own separate user account. In the following
|
||||||
|
we assume this user is called nominatim and the installation will be in
|
||||||
|
/srv/nominatim. To create the user and directory run:
|
||||||
|
|
||||||
|
sudo useradd -d /srv/nominatim -s /bin/bash -m nominatim
|
||||||
|
|
||||||
|
You may find a more suitable location if you wish.
|
||||||
|
|
||||||
|
To be able to copy and paste instructions from this manual, export
|
||||||
|
user name and home directory now like this:
|
||||||
|
|
||||||
|
export USERNAME=nominatim
|
||||||
|
export USERHOME=/srv/nominatim
|
||||||
|
|
||||||
|
**Never, ever run the installation as a root user.** You have been warned.
|
||||||
|
|
||||||
|
Make sure that system servers can read from the home directory:
|
||||||
|
|
||||||
|
chmod a+x $USERHOME
|
||||||
|
|
||||||
|
Setting up PostgreSQL
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Tune the postgresql configuration, which is located in
|
||||||
|
`/etc/postgresql/9.5/main/postgresql.conf`. See section *Postgres Tuning* in
|
||||||
|
[the installation page](Installation.md) for the parameters to change.
|
||||||
|
|
||||||
|
Restart the postgresql service after updating this config file.
|
||||||
|
|
||||||
|
sudo systemctl restart postgresql
|
||||||
|
|
||||||
|
|
||||||
|
Finally, we need to add two postgres users: one for the user that does
|
||||||
|
the import and another for the webserver which should access the database
|
||||||
|
for reading only:
|
||||||
|
|
||||||
|
|
||||||
|
sudo -u postgres createuser -s $USERNAME
|
||||||
|
sudo -u postgres createuser www-data
|
||||||
|
|
||||||
|
|
||||||
|
Setting up the Apache Webserver
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
You need to create an alias to the website directory in your apache
|
||||||
|
configuration. Add a separate nominatim configuration to your webserver:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo tee /etc/apache2/conf-available/nominatim.conf << EOFAPACHECONF
|
||||||
|
<Directory "$USERHOME/Nominatim/build/website">
|
||||||
|
Options FollowSymLinks MultiViews
|
||||||
|
AddType text/html .php
|
||||||
|
DirectoryIndex search.php
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
Alias /nominatim $USERHOME/Nominatim/build/website
|
||||||
|
EOFAPACHECONF
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Then enable the configuration and restart apache
|
||||||
|
|
||||||
|
|
||||||
|
sudo a2enconf nominatim
|
||||||
|
sudo systemctl restart apache2
|
||||||
|
|
||||||
|
|
||||||
|
Installing Nominatim
|
||||||
|
====================
|
||||||
|
|
||||||
|
Building and Configuration
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Get the source code from Github and change into the source directory
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cd $USERHOME
|
||||||
|
git clone --recursive git://github.com/openstreetmap/Nominatim.git
|
||||||
|
cd Nominatim
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
When installing the latest source from github, you also need to
|
||||||
|
download the country grid:
|
||||||
|
|
||||||
|
|
||||||
|
wget -O data/country_osm_grid.sql.gz http://www.nominatim.org/data/country_grid.sql.gz
|
||||||
|
|
||||||
|
|
||||||
|
The code must be built in a separate directory. Create this directory,
|
||||||
|
then configure and build Nominatim in there:
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake $USERHOME/Nominatim
|
||||||
|
make
|
||||||
|
|
||||||
|
You need to create a minimal configuration file that tells nominatim
|
||||||
|
where it is located on the webserver:
|
||||||
|
|
||||||
|
```
|
||||||
|
tee settings/local.php << EOF
|
||||||
|
<?php
|
||||||
|
@define('CONST_Website_BaseURL', '/nominatim/');
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Nominatim is now ready to use. Continue with
|
||||||
|
[importing a database from OSM data](Import-and-Update.md).
|
||||||
154
docs/Installation.md
Normal file
154
docs/Installation.md
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
Nominatim installation
|
||||||
|
======================
|
||||||
|
|
||||||
|
This page contains generic installation instructions for Nominatim and its
|
||||||
|
prerequisites. There are also step-by-step instructions available for
|
||||||
|
the following operating systems:
|
||||||
|
|
||||||
|
* [Ubuntu 16.04](Install-on-Ubuntu-16.md)
|
||||||
|
* [CentOS 7.2](Install-on-Centos-7.md)
|
||||||
|
|
||||||
|
These OS-specific instructions can also be found in executable form
|
||||||
|
in the `vagrant/` directory.
|
||||||
|
|
||||||
|
Prerequisites
|
||||||
|
-------------
|
||||||
|
|
||||||
|
### Software
|
||||||
|
|
||||||
|
For compiling:
|
||||||
|
|
||||||
|
* [cmake](https://cmake.org/)
|
||||||
|
* [libxml2](http://xmlsoft.org/)
|
||||||
|
* a recent C++ compiler
|
||||||
|
|
||||||
|
Nominatim comes with its own version of osm2pgsql. See the
|
||||||
|
[osm2pgsql README](../osm2pgsql/README.md) for additional dependencies
|
||||||
|
required for compiling osm2pgsql.
|
||||||
|
|
||||||
|
For running tests:
|
||||||
|
|
||||||
|
* [behave](http://pythonhosted.org/behave/)
|
||||||
|
* [Psycopg2](http://initd.org/psycopg)
|
||||||
|
* [nose](https://nose.readthedocs.io)
|
||||||
|
* [phpunit](https://phpunit.de)
|
||||||
|
|
||||||
|
For running Nominatim:
|
||||||
|
|
||||||
|
* [PostgreSQL](http://www.postgresql.org) (9.1 or later)
|
||||||
|
* [PostGIS](http://postgis.refractions.net) (2.0 or later)
|
||||||
|
* [PHP](http://php.net) (5.4 or later)
|
||||||
|
* PHP-pgsql
|
||||||
|
* PHP-intl (bundled with PHP)
|
||||||
|
* [PEAR::DB](http://pear.php.net/package/DB)
|
||||||
|
* a webserver (apache or nginx are recommended)
|
||||||
|
|
||||||
|
For running continuous updates:
|
||||||
|
|
||||||
|
* [pyosmium](http://osmcode.org/pyosmium/)
|
||||||
|
|
||||||
|
### Hardware
|
||||||
|
|
||||||
|
A minimum of 2GB of RAM is required or installation will fail. For a full
|
||||||
|
planet import 32GB of RAM or more strongly are recommended.
|
||||||
|
|
||||||
|
For a full planet install you will need about 500GB of hard disk space (as of
|
||||||
|
June 2016, take into account that the OSM database is growing fast). SSD disks
|
||||||
|
will help considerably to speed up import and queries.
|
||||||
|
|
||||||
|
On a 6-core machine with 32GB RAM and SSDs the import of a full planet takes
|
||||||
|
a bit more than 2 days. Without SSDs 7-8 days are more realistic.
|
||||||
|
|
||||||
|
|
||||||
|
Setup of the server
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### PostgreSQL tuning
|
||||||
|
|
||||||
|
You might want to tune your PostgreSQL installation so that the later steps
|
||||||
|
make best use of your hardware. You should tune the following parameters in
|
||||||
|
your `postgresql.conf` file.
|
||||||
|
|
||||||
|
shared_buffers (2GB)
|
||||||
|
maintenance_work_mem (10GB)
|
||||||
|
work_mem (50MB)
|
||||||
|
effective_cache_size (24GB)
|
||||||
|
synchronous_commit = off
|
||||||
|
checkpoint_segments = 100 # only for postgresql <= 9.4
|
||||||
|
checkpoint_timeout = 10min
|
||||||
|
checkpoint_completion_target = 0.9
|
||||||
|
|
||||||
|
The numbers in brackets behind some parameters seem to work fine for
|
||||||
|
32GB RAM machine. Adjust to your setup.
|
||||||
|
|
||||||
|
For the initial import, you should also set:
|
||||||
|
|
||||||
|
fsync = off
|
||||||
|
full_page_writes = off
|
||||||
|
|
||||||
|
Don't forget to reenable them after the initial import or you risk database
|
||||||
|
corruption. Autovacuum must not be switched off because it ensures that the
|
||||||
|
tables are frequently analysed.
|
||||||
|
|
||||||
|
### Webserver setup
|
||||||
|
|
||||||
|
The `website/` directory in the build directory contains the configured
|
||||||
|
website. Include the directory into your webbrowser to serve php files
|
||||||
|
from there.
|
||||||
|
|
||||||
|
#### Configure for use with Apache
|
||||||
|
|
||||||
|
Make sure your Apache configuration contains the required permissions for the
|
||||||
|
directory and create an alias:
|
||||||
|
|
||||||
|
<Directory "/srv/nominatim/build/website">
|
||||||
|
Options FollowSymLinks MultiViews
|
||||||
|
AddType text/html .php
|
||||||
|
DirectoryIndex search.php
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
Alias /nominatim /srv/nominatim/build/website
|
||||||
|
|
||||||
|
`/srv/nominatim/build` should be replaced with the location of your
|
||||||
|
build directory.
|
||||||
|
|
||||||
|
After making changes in the apache config you need to restart apache.
|
||||||
|
The website should now be available on http://localhost/nominatim.
|
||||||
|
|
||||||
|
#### Configure for use with Nginx
|
||||||
|
|
||||||
|
Use php-fpm as a deamon for serving PHP cgi. Install php-fpm together with nginx.
|
||||||
|
|
||||||
|
By default php listens on a network socket. If you want it to listen to a
|
||||||
|
Unix socket instead, change the pool configuration (`pool.d/www.conf`) as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
; Comment out the tcp listener and add the unix socket
|
||||||
|
;listen = 127.0.0.1:9000
|
||||||
|
listen = /var/run/php5-fpm.sock
|
||||||
|
|
||||||
|
; Ensure that the daemon runs as the correct user
|
||||||
|
listen.owner = www-data
|
||||||
|
listen.group = www-data
|
||||||
|
listen.mode = 0666
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
root /srv/nominatim/build/website;
|
||||||
|
index search.php index.html;
|
||||||
|
location ~ [^/]\.php(/|$) {
|
||||||
|
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
||||||
|
if (!-f $document_root$fastcgi_script_name) {
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
fastcgi_pass unix:/var/run/php5-fpm.sock;
|
||||||
|
fastcgi_index search.php;
|
||||||
|
include fastcgi.conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
Restart the nginx and php5-fpm services and the website should now be available
|
||||||
|
on http://localhost/.
|
||||||
|
|
||||||
|
|
||||||
|
Now continue with [importing the database](Import-and-Update.md).
|
||||||
7
docs/bash2md.sh
Executable file
7
docs/bash2md.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Extract markdown-formatted documentation from a source file
|
||||||
|
#
|
||||||
|
# Usage: bash2md.sh <infile> <outfile>
|
||||||
|
|
||||||
|
sed '/^#!/d;s:^#\( \|$\)::;s/.*#DOCS://' $1 > $2
|
||||||
1939
lib/Geocode.php
1939
lib/Geocode.php
File diff suppressed because it is too large
Load Diff
157
lib/NearPoint.php
Normal file
157
lib/NearPoint.php
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nominatim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A geographic point with a search radius.
|
||||||
|
*/
|
||||||
|
class NearPoint
|
||||||
|
{
|
||||||
|
private $fLat;
|
||||||
|
private $fLon;
|
||||||
|
private $fRadius;
|
||||||
|
|
||||||
|
private $sSQL;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct($lat, $lon, $radius = 0.1)
|
||||||
|
{
|
||||||
|
$this->fLat = (float)$lat;
|
||||||
|
$this->fLon = (float)$lon;
|
||||||
|
$this->fRadius = (float)$radius;
|
||||||
|
$this->sSQL = 'ST_SetSRID(ST_Point('.$this->fLon.','.$this->fLat.'),4326)';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function lat()
|
||||||
|
{
|
||||||
|
return $this->fLat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function lon()
|
||||||
|
{
|
||||||
|
return $this->fLon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function radius()
|
||||||
|
{
|
||||||
|
return $this->fRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function distanceSQL($sObj)
|
||||||
|
{
|
||||||
|
return 'ST_Distance('.$this->sSQL.", $sObj)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withinSQL($sObj)
|
||||||
|
{
|
||||||
|
return sprintf('ST_DWithin(%s, %s, %F)', $sObj, $this->sSQL, $this->fRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the coordinates are valid WSG84 coordinates.
|
||||||
|
*
|
||||||
|
* @return bool True if the coordinates are correctly bounded.
|
||||||
|
*/
|
||||||
|
public function isValid()
|
||||||
|
{
|
||||||
|
return ($this->fLat <= 90.1
|
||||||
|
&& $this->fLat >= -90.1
|
||||||
|
&& $this->fLon <= 180.1
|
||||||
|
&& $this->fLon >= -180.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract a coordinate point from a query string.
|
||||||
|
*
|
||||||
|
* If a coordinate is found an array of a new NearPoint and the
|
||||||
|
* remaining query is returned or false otherwise.
|
||||||
|
*
|
||||||
|
* @param string $sQuery Query to scan.
|
||||||
|
*
|
||||||
|
* @return array|false If a coordinate was found, an array with
|
||||||
|
* `pt` as the NearPoint coordinates and `query`
|
||||||
|
* with the remaining query string. False otherwiese.
|
||||||
|
*/
|
||||||
|
public static function extractFromQuery($sQuery)
|
||||||
|
{
|
||||||
|
// Do we have anything that looks like a lat/lon pair?
|
||||||
|
// returns array(lat,lon,query_with_lat_lon_removed)
|
||||||
|
// or null
|
||||||
|
$sFound = null;
|
||||||
|
$fQueryLat = null;
|
||||||
|
$fQueryLon = null;
|
||||||
|
|
||||||
|
if (preg_match('/\\b([NS])[ ]+([0-9]+[0-9.]*)[° ]+([0-9.]+)?[′\']*[, ]+([EW])[ ]+([0-9]+)[° ]+([0-9]+[0-9.]*)[′\']*?\\b/', $sQuery, $aData)) {
|
||||||
|
/* 1 2 3 4 5 6
|
||||||
|
* degrees decimal minutes
|
||||||
|
* N 40 26.767, W 79 58.933
|
||||||
|
* N 40°26.767′, W 79°58.933′
|
||||||
|
*/
|
||||||
|
$sFound = $aData[0];
|
||||||
|
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60);
|
||||||
|
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[5] + $aData[6]/60);
|
||||||
|
} elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+[0-9.]*)?[′\']*[ ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+[0-9.]*)?[′\' ]+([EW])\\b/', $sQuery, $aData)) {
|
||||||
|
/* 1 2 3 4 5 6
|
||||||
|
* degrees decimal minutes
|
||||||
|
* 40 26.767 N, 79 58.933 W
|
||||||
|
* 40° 26.767′ N 79° 58.933′ W
|
||||||
|
*/
|
||||||
|
$sFound = $aData[0];
|
||||||
|
$fQueryLat = ($aData[3]=='N'?1:-1) * ($aData[1] + $aData[2]/60);
|
||||||
|
$fQueryLon = ($aData[6]=='E'?1:-1) * ($aData[4] + $aData[5]/60);
|
||||||
|
} elseif (preg_match('/\\b([NS])[ ]([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″"]*[, ]+([EW])[ ]([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″"]*\\b/', $sQuery, $aData)) {
|
||||||
|
/* 1 2 3 4 5 6 7 8
|
||||||
|
* degrees decimal seconds
|
||||||
|
* N 40 26 46 W 79 58 56
|
||||||
|
* N 40° 26′ 46″, W 79° 58′ 56″
|
||||||
|
*/
|
||||||
|
$sFound = $aData[0];
|
||||||
|
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60 + $aData[4]/3600);
|
||||||
|
$fQueryLon = ($aData[5]=='E'?1:-1) * ($aData[6] + $aData[7]/60 + $aData[8]/3600);
|
||||||
|
} elseif (preg_match('/\\b([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″" ]+([NS])[, ]+([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″" ]+([EW])\\b/', $sQuery, $aData)) {
|
||||||
|
/* 1 2 3 4 5 6 7 8
|
||||||
|
* degrees decimal seconds
|
||||||
|
* 40 26 46 N 79 58 56 W
|
||||||
|
* 40° 26′ 46″ N, 79° 58′ 56″ W
|
||||||
|
*/
|
||||||
|
$sFound = $aData[0];
|
||||||
|
$fQueryLat = ($aData[4]=='N'?1:-1) * ($aData[1] + $aData[2]/60 + $aData[3]/3600);
|
||||||
|
$fQueryLon = ($aData[8]=='E'?1:-1) * ($aData[5] + $aData[6]/60 + $aData[7]/3600);
|
||||||
|
} elseif (preg_match('/\\b([NS])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*[, ]+([EW])[ ]([0-9]+[0-9]*\\.[0-9]+)[°]*\\b/', $sQuery, $aData)) {
|
||||||
|
/* 1 2 3 4
|
||||||
|
* degrees decimal
|
||||||
|
* N 40.446° W 79.982°
|
||||||
|
*/
|
||||||
|
$sFound = $aData[0];
|
||||||
|
$fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2]);
|
||||||
|
$fQueryLon = ($aData[3]=='E'?1:-1) * ($aData[4]);
|
||||||
|
} elseif (preg_match('/\\b([0-9]+[0-9]*\\.[0-9]+)[° ]+([NS])[, ]+([0-9]+[0-9]*\\.[0-9]+)[° ]+([EW])\\b/', $sQuery, $aData)) {
|
||||||
|
/* 1 2 3 4
|
||||||
|
* degrees decimal
|
||||||
|
* 40.446° N 79.982° W
|
||||||
|
*/
|
||||||
|
$sFound = $aData[0];
|
||||||
|
$fQueryLat = ($aData[2]=='N'?1:-1) * ($aData[1]);
|
||||||
|
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[3]);
|
||||||
|
} elseif (preg_match('/(\\[|^|\\b)(-?[0-9]+[0-9]*\\.[0-9]+)[, ]+(-?[0-9]+[0-9]*\\.[0-9]+)(\\]|$|\\b)/', $sQuery, $aData)) {
|
||||||
|
/* 1 2 3 4
|
||||||
|
* degrees decimal
|
||||||
|
* 12.34, 56.78
|
||||||
|
* [12.456,-78.90]
|
||||||
|
*/
|
||||||
|
$sFound = $aData[0];
|
||||||
|
$fQueryLat = $aData[2];
|
||||||
|
$fQueryLon = $aData[3];
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oPt = new NearPoint($fQueryLat, $fQueryLon);
|
||||||
|
|
||||||
|
if (!$oPt->isValid()) return false;
|
||||||
|
|
||||||
|
$sQuery = trim(str_replace($sFound, ' ', $sQuery));
|
||||||
|
|
||||||
|
return array('pt' => $oPt, 'query' => $sQuery);
|
||||||
|
}
|
||||||
|
}
|
||||||
120
lib/ParameterParser.php
Normal file
120
lib/ParameterParser.php
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nominatim;
|
||||||
|
|
||||||
|
class ParameterParser
|
||||||
|
{
|
||||||
|
private $aParams;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct($aParams = null)
|
||||||
|
{
|
||||||
|
$this->aParams = ($aParams === null) ? $_GET : $aParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBool($sName, $bDefault = false)
|
||||||
|
{
|
||||||
|
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
|
||||||
|
return $bDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bool) $this->aParams[$sName];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInt($sName, $bDefault = false)
|
||||||
|
{
|
||||||
|
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
|
||||||
|
return $bDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preg_match('/^[+-]?[0-9]+$/', $this->aParams[$sName])) {
|
||||||
|
userError("Integer number expected for parameter '$sName'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) $this->aParams[$sName];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFloat($sName, $bDefault = false)
|
||||||
|
{
|
||||||
|
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
|
||||||
|
return $bDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preg_match('/^[+-]?[0-9]*\.?[0-9]+$/', $this->aParams[$sName])) {
|
||||||
|
userError("Floating-point number expected for parameter '$sName'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (float) $this->aParams[$sName];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getString($sName, $bDefault = false)
|
||||||
|
{
|
||||||
|
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
|
||||||
|
return $bDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->aParams[$sName];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSet($sName, $aValues, $sDefault = false)
|
||||||
|
{
|
||||||
|
if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
|
||||||
|
return $sDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array($this->aParams[$sName], $aValues)) {
|
||||||
|
userError("Parameter '$sName' must be one of: ".join(', ', $aValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->aParams[$sName];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStringList($sName, $aDefault = false)
|
||||||
|
{
|
||||||
|
$sValue = $this->getString($sName);
|
||||||
|
|
||||||
|
if ($sValue) {
|
||||||
|
return explode(',', $sValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreferredLanguages($sFallback = null)
|
||||||
|
{
|
||||||
|
if ($sFallback === null && isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) {
|
||||||
|
$sFallback = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
|
||||||
|
}
|
||||||
|
|
||||||
|
$aLanguages = array();
|
||||||
|
$sLangString = $this->getString('accept-language', $sFallback);
|
||||||
|
|
||||||
|
if ($sLangString) {
|
||||||
|
if (preg_match_all('/(([a-z]{1,8})(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $sLangString, $aLanguagesParse, PREG_SET_ORDER)) {
|
||||||
|
foreach ($aLanguagesParse as $iLang => $aLanguage) {
|
||||||
|
$aLanguages[$aLanguage[1]] = isset($aLanguage[5])?(float)$aLanguage[5]:1 - ($iLang/100);
|
||||||
|
if (!isset($aLanguages[$aLanguage[2]])) $aLanguages[$aLanguage[2]] = $aLanguages[$aLanguage[1]]/10;
|
||||||
|
}
|
||||||
|
arsort($aLanguages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!sizeof($aLanguages) && CONST_Default_Language) {
|
||||||
|
$aLanguages[CONST_Default_Language] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($aLanguages as $sLanguage => $fLanguagePref) {
|
||||||
|
$aLangPrefOrder['short_name:'.$sLanguage] = 'short_name:'.$sLanguage;
|
||||||
|
$aLangPrefOrder['name:'.$sLanguage] = 'name:'.$sLanguage;
|
||||||
|
}
|
||||||
|
$aLangPrefOrder['short_name'] = 'short_name';
|
||||||
|
$aLangPrefOrder['name'] = 'name';
|
||||||
|
$aLangPrefOrder['brand'] = 'brand';
|
||||||
|
foreach ($aLanguages as $sLanguage => $fLanguagePref) {
|
||||||
|
$aLangPrefOrder['official_name:'.$sLanguage] = 'official_name:'.$sLanguage;
|
||||||
|
}
|
||||||
|
$aLangPrefOrder['official_name'] = 'official_name';
|
||||||
|
$aLangPrefOrder['ref'] = 'ref';
|
||||||
|
$aLangPrefOrder['type'] = 'type';
|
||||||
|
return $aLangPrefOrder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,144 +1,179 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
namespace Nominatim;
|
||||||
|
|
||||||
class PlaceLookup
|
class PlaceLookup
|
||||||
{
|
{
|
||||||
protected $oDB;
|
protected $oDB;
|
||||||
|
|
||||||
protected $iPlaceID;
|
|
||||||
|
|
||||||
protected $sType = false;
|
|
||||||
|
|
||||||
protected $aLangPrefOrder = array();
|
protected $aLangPrefOrder = array();
|
||||||
|
|
||||||
protected $bAddressDetails = false;
|
protected $bAddressDetails = false;
|
||||||
|
|
||||||
protected $bExtraTags = false;
|
protected $bExtraTags = false;
|
||||||
|
|
||||||
protected $bNameDetails = false;
|
protected $bNameDetails = false;
|
||||||
|
|
||||||
function PlaceLookup(&$oDB)
|
protected $bIncludePolygonAsPoints = false;
|
||||||
|
protected $bIncludePolygonAsText = false;
|
||||||
|
protected $bIncludePolygonAsGeoJSON = false;
|
||||||
|
protected $bIncludePolygonAsKML = false;
|
||||||
|
protected $bIncludePolygonAsSVG = false;
|
||||||
|
protected $fPolygonSimplificationThreshold = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(&$oDB)
|
||||||
{
|
{
|
||||||
$this->oDB =& $oDB;
|
$this->oDB =& $oDB;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLanguagePreference($aLangPrefOrder)
|
public function setLanguagePreference($aLangPrefOrder)
|
||||||
{
|
{
|
||||||
$this->aLangPrefOrder = $aLangPrefOrder;
|
$this->aLangPrefOrder = $aLangPrefOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setIncludeAddressDetails($bAddressDetails = true)
|
public function setIncludeAddressDetails($bAddressDetails = true)
|
||||||
{
|
{
|
||||||
$this->bAddressDetails = $bAddressDetails;
|
$this->bAddressDetails = $bAddressDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setIncludeExtraTags($bExtraTags = false)
|
public function setIncludeExtraTags($bExtraTags = false)
|
||||||
{
|
|
||||||
if ((float) CONST_Postgresql_Version > 9.2)
|
|
||||||
{
|
{
|
||||||
$this->bExtraTags = $bExtraTags;
|
$this->bExtraTags = $bExtraTags;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function setIncludeNameDetails($bNameDetails = false)
|
public function setIncludeNameDetails($bNameDetails = false)
|
||||||
{
|
|
||||||
if ((float) CONST_Postgresql_Version > 9.2)
|
|
||||||
{
|
{
|
||||||
$this->bNameDetails = $bNameDetails;
|
$this->bNameDetails = $bNameDetails;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function setPlaceID($iPlaceID)
|
|
||||||
|
public function setIncludePolygonAsPoints($b = true)
|
||||||
{
|
{
|
||||||
$this->iPlaceID = $iPlaceID;
|
$this->bIncludePolygonAsPoints = $b;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setOSMID($sType, $iID)
|
public function getIncludePolygonAsPoints()
|
||||||
|
{
|
||||||
|
return $this->bIncludePolygonAsPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIncludePolygonAsText($b = true)
|
||||||
|
{
|
||||||
|
$this->bIncludePolygonAsText = $b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIncludePolygonAsText()
|
||||||
|
{
|
||||||
|
return $this->bIncludePolygonAsText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIncludePolygonAsGeoJSON($b = true)
|
||||||
|
{
|
||||||
|
$this->bIncludePolygonAsGeoJSON = $b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIncludePolygonAsKML($b = true)
|
||||||
|
{
|
||||||
|
$this->bIncludePolygonAsKML = $b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIncludePolygonAsSVG($b = true)
|
||||||
|
{
|
||||||
|
$this->bIncludePolygonAsSVG = $b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPolygonSimplificationThreshold($f)
|
||||||
|
{
|
||||||
|
$this->fPolygonSimplificationThreshold = $f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function lookupOSMID($sType, $iID)
|
||||||
{
|
{
|
||||||
$sSQL = "select place_id from placex where osm_type = '".pg_escape_string($sType)."' and osm_id = ".(int)$iID." order by type = 'postcode' asc";
|
$sSQL = "select place_id from placex where osm_type = '".pg_escape_string($sType)."' and osm_id = ".(int)$iID." order by type = 'postcode' asc";
|
||||||
$this->iPlaceID = $this->oDB->getOne($sSQL);
|
$iPlaceID = chksql($this->oDB->getOne($sSQL));
|
||||||
|
|
||||||
|
return $this->lookup((int)$iPlaceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
function lookupPlace($details)
|
public function lookup($iPlaceID, $sType = '', $fInterpolFraction = 0.0)
|
||||||
{
|
{
|
||||||
if (isset($details['place_id'])) $this->iPlaceID = $details['place_id'];
|
if (!$iPlaceID) return null;
|
||||||
if (isset($details['type'])) $this->sType = $details['type'];
|
|
||||||
if (isset($details['osm_type']) && isset($details['osm_id']))
|
|
||||||
{
|
|
||||||
$this->setOSMID($details['osm_type'], $details['osm_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->lookup();
|
|
||||||
}
|
|
||||||
|
|
||||||
function lookup()
|
|
||||||
{
|
|
||||||
if (!$this->iPlaceID) return null;
|
|
||||||
|
|
||||||
$sLanguagePrefArraySQL = "ARRAY[".join(',', array_map("getDBQuoted", $this->aLangPrefOrder))."]";
|
$sLanguagePrefArraySQL = "ARRAY[".join(',', array_map("getDBQuoted", $this->aLangPrefOrder))."]";
|
||||||
|
$bIsTiger = CONST_Use_US_Tiger_Data && $sType == 'tiger';
|
||||||
|
$bIsInterpolation = $sType == 'interpolation';
|
||||||
|
|
||||||
if ($this->sType == 'tiger')
|
if ($bIsTiger) {
|
||||||
{
|
$sSQL = "select place_id,partition, 'T' as osm_type, place_id as osm_id, 'place' as class, 'house' as type, null as admin_level, housenumber, postcode,";
|
||||||
$sSQL = "select place_id,partition, 'T' as osm_type, place_id as osm_id, 'place' as class, 'house' as type, null as admin_level, housenumber, null as street, null as isin, postcode,";
|
|
||||||
$sSQL .= " 'us' as country_code, parent_place_id, null as linked_place_id, 30 as rank_address, 30 as rank_search,";
|
$sSQL .= " 'us' as country_code, parent_place_id, null as linked_place_id, 30 as rank_address, 30 as rank_search,";
|
||||||
$sSQL .= " coalesce(null,0.75-(30::float/40)) as importance, null as indexed_status, null as indexed_date, null as wikipedia, 'us' as calculated_country_code, ";
|
$sSQL .= " coalesce(null,0.75-(30::float/40)) as importance, null as indexed_status, null as indexed_date, null as wikipedia, 'us' as country_code, ";
|
||||||
$sSQL .= " get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
|
$sSQL .= " get_address_by_language(place_id, housenumber, $sLanguagePrefArraySQL) as langaddress,";
|
||||||
$sSQL .= " null as placename,";
|
$sSQL .= " null as placename,";
|
||||||
$sSQL .= " null as ref,";
|
$sSQL .= " null as ref,";
|
||||||
if ($this->bExtraTags) $sSQL .= " null as extra,";
|
if ($this->bExtraTags) $sSQL .= " null as extra,";
|
||||||
if ($this->bNameDetails) $sSQL .= " null as names,";
|
if ($this->bNameDetails) $sSQL .= " null as names,";
|
||||||
$sSQL .= " st_y(centroid) as lat,";
|
$sSQL .= " ST_X(point) as lon, ST_Y(point) as lat from (select *, ST_LineInterpolatePoint(linegeo, (housenumber-startnumber::float)/(endnumber-startnumber)::float) as point from ";
|
||||||
$sSQL .= " st_x(centroid) as lon";
|
$sSQL .= " (select *, ";
|
||||||
$sSQL .= " from location_property_tiger where place_id = ".(int)$this->iPlaceID;
|
$sSQL .= " CASE WHEN interpolationtype='odd' THEN floor((".$fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2+1";
|
||||||
}
|
$sSQL .= " WHEN interpolationtype='even' THEN ((".$fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2";
|
||||||
else
|
$sSQL .= " WHEN interpolationtype='all' THEN (".$fInterpolFraction."*(endnumber-startnumber)+startnumber)::int";
|
||||||
{
|
$sSQL .= " END as housenumber";
|
||||||
$sSQL = "select placex.place_id, partition, osm_type, osm_id, class, type, admin_level, housenumber, street, isin, postcode, country_code, parent_place_id, linked_place_id, rank_address, rank_search, ";
|
$sSQL .= " from location_property_tiger where place_id = ".$iPlaceID.") as blub1) as blub2";
|
||||||
$sSQL .= " coalesce(importance,0.75-(rank_search::float/40)) as importance, indexed_status, indexed_date, wikipedia, calculated_country_code, ";
|
} elseif ($bIsInterpolation) {
|
||||||
$sSQL .= " get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
|
$sSQL = "select place_id, partition, 'W' as osm_type, osm_id, 'place' as class, 'house' as type, null admin_level, housenumber, postcode,";
|
||||||
|
$sSQL .= " country_code, parent_place_id, null as linked_place_id, 30 as rank_address, 30 as rank_search,";
|
||||||
|
$sSQL .= " (0.75-(30::float/40)) as importance, null as indexed_status, null as indexed_date, null as wikipedia, country_code, ";
|
||||||
|
$sSQL .= " get_address_by_language(place_id, housenumber, $sLanguagePrefArraySQL) as langaddress,";
|
||||||
|
$sSQL .= " null as placename,";
|
||||||
|
$sSQL .= " null as ref,";
|
||||||
|
if ($this->bExtraTags) $sSQL .= " null as extra,";
|
||||||
|
if ($this->bNameDetails) $sSQL .= " null as names,";
|
||||||
|
$sSQL .= " ST_X(point) as lon, ST_Y(point) as lat from (select *, ST_LineInterpolatePoint(linegeo, (housenumber-startnumber::float)/(endnumber-startnumber)::float) as point from ";
|
||||||
|
$sSQL .= " (select *, ";
|
||||||
|
$sSQL .= " CASE WHEN interpolationtype='odd' THEN floor((".$fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2+1";
|
||||||
|
$sSQL .= " WHEN interpolationtype='even' THEN ((".$fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2";
|
||||||
|
$sSQL .= " WHEN interpolationtype='all' THEN (".$fInterpolFraction."*(endnumber-startnumber)+startnumber)::int";
|
||||||
|
$sSQL .= " END as housenumber";
|
||||||
|
$sSQL .= " from location_property_osmline where place_id = ".$iPlaceID.") as blub1) as blub2";
|
||||||
|
// testcase: interpolationtype=odd, startnumber=1000, endnumber=1006, fInterpolFraction=1 => housenumber=1007 => error in st_lineinterpolatepoint
|
||||||
|
// but this will never happen, because if the searched point is that close to the endnumber, the endnumber house will be directly taken from placex (in ReverseGeocode.php line 220)
|
||||||
|
// and not interpolated
|
||||||
|
} else {
|
||||||
|
$sSQL = "select placex.place_id, partition, osm_type, osm_id, class,";
|
||||||
|
$sSQL .= " type, admin_level, housenumber, postcode, country_code,";
|
||||||
|
$sSQL .= " parent_place_id, linked_place_id, rank_address, rank_search, ";
|
||||||
|
$sSQL .= " coalesce(importance,0.75-(rank_search::float/40)) as importance, indexed_status, indexed_date, wikipedia, country_code, ";
|
||||||
|
$sSQL .= " get_address_by_language(place_id, -1, $sLanguagePrefArraySQL) as langaddress,";
|
||||||
$sSQL .= " get_name_by_language(name, $sLanguagePrefArraySQL) as placename,";
|
$sSQL .= " get_name_by_language(name, $sLanguagePrefArraySQL) as placename,";
|
||||||
$sSQL .= " get_name_by_language(name, ARRAY['ref']) as ref,";
|
$sSQL .= " get_name_by_language(name, ARRAY['ref']) as ref,";
|
||||||
if ($this->bExtraTags) $sSQL .= " hstore_to_json(extratags) as extra,";
|
if ($this->bExtraTags) $sSQL .= " hstore_to_json(extratags) as extra,";
|
||||||
if ($this->bNameDetails) $sSQL .= " hstore_to_json(name) as names,";
|
if ($this->bNameDetails) $sSQL .= " hstore_to_json(name) as names,";
|
||||||
$sSQL .= " (case when centroid is null then st_y(st_centroid(geometry)) else st_y(centroid) end) as lat,";
|
$sSQL .= " (case when centroid is null then st_y(st_centroid(geometry)) else st_y(centroid) end) as lat,";
|
||||||
$sSQL .= " (case when centroid is null then st_x(st_centroid(geometry)) else st_x(centroid) end) as lon";
|
$sSQL .= " (case when centroid is null then st_x(st_centroid(geometry)) else st_x(centroid) end) as lon";
|
||||||
$sSQL .= " from placex where place_id = ".(int)$this->iPlaceID;
|
$sSQL .= " from placex where place_id = ".$iPlaceID;
|
||||||
}
|
}
|
||||||
|
|
||||||
$aPlace = $this->oDB->getRow($sSQL);
|
$aPlace = chksql($this->oDB->getRow($sSQL), "Could not lookup place");
|
||||||
|
|
||||||
|
|
||||||
if (PEAR::IsError($aPlace))
|
|
||||||
{
|
|
||||||
failInternalError("Could not lookup place.", $sSQL, $aPlace);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$aPlace['place_id']) return null;
|
if (!$aPlace['place_id']) return null;
|
||||||
|
|
||||||
if ($this->bAddressDetails)
|
if ($this->bAddressDetails) {
|
||||||
{
|
// to get addressdetails for tiger data, the housenumber is needed
|
||||||
$aAddress = $this->getAddressNames();
|
$iHousenumber = ($bIsTiger || $bIsInterpolation) ? $aPlace['housenumber'] : -1;
|
||||||
$aPlace['aAddress'] = $aAddress;
|
$aPlace['aAddress'] = $this->getAddressNames($aPlace['place_id'], $iHousenumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->bExtraTags)
|
if ($this->bExtraTags) {
|
||||||
{
|
if ($aPlace['extra']) {
|
||||||
if ($aPlace['extra'])
|
|
||||||
{
|
|
||||||
$aPlace['sExtraTags'] = json_decode($aPlace['extra']);
|
$aPlace['sExtraTags'] = json_decode($aPlace['extra']);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aPlace['sExtraTags'] = (object) array();
|
$aPlace['sExtraTags'] = (object) array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->bNameDetails)
|
if ($this->bNameDetails) {
|
||||||
{
|
if ($aPlace['names']) {
|
||||||
if ($aPlace['names'])
|
|
||||||
{
|
|
||||||
$aPlace['sNameDetails'] = json_decode($aPlace['names']);
|
$aPlace['sNameDetails'] = json_decode($aPlace['names']);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aPlace['sNameDetails'] = (object) array();
|
$aPlace['sNameDetails'] = (object) array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,12 +181,9 @@
|
|||||||
$aClassType = getClassTypes();
|
$aClassType = getClassTypes();
|
||||||
$sAddressType = '';
|
$sAddressType = '';
|
||||||
$sClassType = $aPlace['class'].':'.$aPlace['type'].':'.$aPlace['admin_level'];
|
$sClassType = $aPlace['class'].':'.$aPlace['type'].':'.$aPlace['admin_level'];
|
||||||
if (isset($aClassType[$sClassType]) && isset($aClassType[$sClassType]['simplelabel']))
|
if (isset($aClassType[$sClassType]) && isset($aClassType[$sClassType]['simplelabel'])) {
|
||||||
{
|
|
||||||
$sAddressType = $aClassType[$aClassType]['simplelabel'];
|
$sAddressType = $aClassType[$aClassType]['simplelabel'];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sClassType = $aPlace['class'].':'.$aPlace['type'];
|
$sClassType = $aPlace['class'].':'.$aPlace['type'];
|
||||||
if (isset($aClassType[$sClassType]) && isset($aClassType[$sClassType]['simplelabel']))
|
if (isset($aClassType[$sClassType]) && isset($aClassType[$sClassType]['simplelabel']))
|
||||||
$sAddressType = $aClassType[$sClassType]['simplelabel'];
|
$sAddressType = $aClassType[$sClassType]['simplelabel'];
|
||||||
@@ -163,54 +195,42 @@
|
|||||||
return $aPlace;
|
return $aPlace;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAddressDetails($bAll = false)
|
public function getAddressDetails($iPlaceID, $bAll = false, $housenumber = -1)
|
||||||
{
|
{
|
||||||
if (!$this->iPlaceID) return null;
|
|
||||||
|
|
||||||
$sLanguagePrefArraySQL = "ARRAY[".join(',', array_map("getDBQuoted", $this->aLangPrefOrder))."]";
|
$sLanguagePrefArraySQL = "ARRAY[".join(',', array_map("getDBQuoted", $this->aLangPrefOrder))."]";
|
||||||
|
|
||||||
$sSQL = "select *,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata(".$this->iPlaceID.")";
|
$sSQL = "select *,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata(".$iPlaceID.",".$housenumber.")";
|
||||||
if (!$bAll) $sSQL .= " WHERE isaddress OR type = 'country_code'";
|
if (!$bAll) $sSQL .= " WHERE isaddress OR type = 'country_code'";
|
||||||
$sSQL .= " order by rank_address desc,isaddress desc";
|
$sSQL .= " order by rank_address desc,isaddress desc";
|
||||||
|
|
||||||
$aAddressLines = $this->oDB->getAll($sSQL);
|
return chksql($this->oDB->getAll($sSQL));
|
||||||
if (PEAR::IsError($aAddressLines))
|
|
||||||
{
|
|
||||||
var_dump($aAddressLines);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
return $aAddressLines;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAddressNames()
|
public function getAddressNames($iPlaceID, $housenumber = -1)
|
||||||
{
|
{
|
||||||
$aAddressLines = $this->getAddressDetails(false);
|
$aAddressLines = $this->getAddressDetails($iPlaceID, false, $housenumber);
|
||||||
|
|
||||||
$aAddress = array();
|
$aAddress = array();
|
||||||
$aFallback = array();
|
$aFallback = array();
|
||||||
$aClassType = getClassTypes();
|
$aClassType = getClassTypes();
|
||||||
foreach($aAddressLines as $aLine)
|
foreach ($aAddressLines as $aLine) {
|
||||||
{
|
|
||||||
$bFallback = false;
|
$bFallback = false;
|
||||||
$aTypeLabel = false;
|
$aTypeLabel = false;
|
||||||
if (isset($aClassType[$aLine['class'].':'.$aLine['type'].':'.$aLine['admin_level']])) $aTypeLabel = $aClassType[$aLine['class'].':'.$aLine['type'].':'.$aLine['admin_level']];
|
if (isset($aClassType[$aLine['class'].':'.$aLine['type'].':'.$aLine['admin_level']])) {
|
||||||
elseif (isset($aClassType[$aLine['class'].':'.$aLine['type']])) $aTypeLabel = $aClassType[$aLine['class'].':'.$aLine['type']];
|
$aTypeLabel = $aClassType[$aLine['class'].':'.$aLine['type'].':'.$aLine['admin_level']];
|
||||||
elseif (isset($aClassType['boundary:administrative:'.((int)($aLine['rank_address']/2))]))
|
} elseif (isset($aClassType[$aLine['class'].':'.$aLine['type']])) {
|
||||||
{
|
$aTypeLabel = $aClassType[$aLine['class'].':'.$aLine['type']];
|
||||||
|
} elseif (isset($aClassType['boundary:administrative:'.((int)($aLine['rank_address']/2))])) {
|
||||||
$aTypeLabel = $aClassType['boundary:administrative:'.((int)($aLine['rank_address']/2))];
|
$aTypeLabel = $aClassType['boundary:administrative:'.((int)($aLine['rank_address']/2))];
|
||||||
$bFallback = true;
|
$bFallback = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aTypeLabel = array('simplelabel' => 'address'.$aLine['rank_address']);
|
$aTypeLabel = array('simplelabel' => 'address'.$aLine['rank_address']);
|
||||||
$bFallback = true;
|
$bFallback = true;
|
||||||
}
|
}
|
||||||
if ($aTypeLabel && ((isset($aLine['localname']) && $aLine['localname']) || (isset($aLine['housenumber']) && $aLine['housenumber'])))
|
if ($aTypeLabel && ((isset($aLine['localname']) && $aLine['localname']) || (isset($aLine['housenumber']) && $aLine['housenumber']))) {
|
||||||
{
|
|
||||||
$sTypeLabel = strtolower(isset($aTypeLabel['simplelabel'])?$aTypeLabel['simplelabel']:$aTypeLabel['label']);
|
$sTypeLabel = strtolower(isset($aTypeLabel['simplelabel'])?$aTypeLabel['simplelabel']:$aTypeLabel['label']);
|
||||||
$sTypeLabel = str_replace(' ', '_', $sTypeLabel);
|
$sTypeLabel = str_replace(' ', '_', $sTypeLabel);
|
||||||
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]) || $aLine['class'] == 'place')
|
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]) || $aLine['class'] == 'place') {
|
||||||
{
|
|
||||||
$aAddress[$sTypeLabel] = $aLine['localname']?$aLine['localname']:$aLine['housenumber'];
|
$aAddress[$sTypeLabel] = $aLine['localname']?$aLine['localname']:$aLine['housenumber'];
|
||||||
}
|
}
|
||||||
$aFallback[$sTypeLabel] = $bFallback;
|
$aFallback[$sTypeLabel] = $bFallback;
|
||||||
@@ -219,5 +239,98 @@
|
|||||||
return $aAddress;
|
return $aAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* returns an array which will contain the keys
|
||||||
|
* aBoundingBox
|
||||||
|
* and may also contain one or more of the keys
|
||||||
|
* asgeojson
|
||||||
|
* askml
|
||||||
|
* assvg
|
||||||
|
* astext
|
||||||
|
* lat
|
||||||
|
* lon
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
public function getOutlines($iPlaceID, $fLon = null, $fLat = null, $fRadius = null)
|
||||||
|
{
|
||||||
|
|
||||||
|
$aOutlineResult = array();
|
||||||
|
if (!$iPlaceID) return $aOutlineResult;
|
||||||
|
|
||||||
|
if (CONST_Search_AreaPolygons) {
|
||||||
|
// Get the bounding box and outline polygon
|
||||||
|
$sSQL = "select place_id,0 as numfeatures,st_area(geometry) as area,";
|
||||||
|
$sSQL .= "ST_Y(centroid) as centrelat,ST_X(centroid) as centrelon,";
|
||||||
|
$sSQL .= "ST_YMin(geometry) as minlat,ST_YMax(geometry) as maxlat,";
|
||||||
|
$sSQL .= "ST_XMin(geometry) as minlon,ST_XMax(geometry) as maxlon";
|
||||||
|
if ($this->bIncludePolygonAsGeoJSON) $sSQL .= ",ST_AsGeoJSON(geometry) as asgeojson";
|
||||||
|
if ($this->bIncludePolygonAsKML) $sSQL .= ",ST_AsKML(geometry) as askml";
|
||||||
|
if ($this->bIncludePolygonAsSVG) $sSQL .= ",ST_AsSVG(geometry) as assvg";
|
||||||
|
if ($this->bIncludePolygonAsText || $this->bIncludePolygonAsPoints) $sSQL .= ",ST_AsText(geometry) as astext";
|
||||||
|
$sFrom = " from placex where place_id = ".$iPlaceID;
|
||||||
|
if ($this->fPolygonSimplificationThreshold > 0) {
|
||||||
|
$sSQL .= " from (select place_id,centroid,ST_SimplifyPreserveTopology(geometry,".$this->fPolygonSimplificationThreshold.") as geometry".$sFrom.") as plx";
|
||||||
|
} else {
|
||||||
|
$sSQL .= $sFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
$aPointPolygon = chksql($this->oDB->getRow($sSQL), "Could not get outline");
|
||||||
|
|
||||||
|
if ($aPointPolygon['place_id']) {
|
||||||
|
if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null) {
|
||||||
|
$aOutlineResult['lat'] = $aPointPolygon['centrelat'];
|
||||||
|
$aOutlineResult['lon'] = $aPointPolygon['centrelon'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->bIncludePolygonAsGeoJSON) $aOutlineResult['asgeojson'] = $aPointPolygon['asgeojson'];
|
||||||
|
if ($this->bIncludePolygonAsKML) $aOutlineResult['askml'] = $aPointPolygon['askml'];
|
||||||
|
if ($this->bIncludePolygonAsSVG) $aOutlineResult['assvg'] = $aPointPolygon['assvg'];
|
||||||
|
if ($this->bIncludePolygonAsText) $aOutlineResult['astext'] = $aPointPolygon['astext'];
|
||||||
|
if ($this->bIncludePolygonAsPoints) $aOutlineResult['aPolyPoints'] = geometryText2Points($aPointPolygon['astext'], $fRadius);
|
||||||
|
|
||||||
|
|
||||||
|
if (abs($aPointPolygon['minlat'] - $aPointPolygon['maxlat']) < 0.0000001) {
|
||||||
|
$aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius;
|
||||||
|
$aPointPolygon['maxlat'] = $aPointPolygon['maxlat'] + $fRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abs($aPointPolygon['minlon'] - $aPointPolygon['maxlon']) < 0.0000001) {
|
||||||
|
$aPointPolygon['minlon'] = $aPointPolygon['minlon'] - $fRadius;
|
||||||
|
$aPointPolygon['maxlon'] = $aPointPolygon['maxlon'] + $fRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
$aOutlineResult['aBoundingBox'] = array(
|
||||||
|
(string)$aPointPolygon['minlat'],
|
||||||
|
(string)$aPointPolygon['maxlat'],
|
||||||
|
(string)$aPointPolygon['minlon'],
|
||||||
|
(string)$aPointPolygon['maxlon']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// as a fallback we generate a bounding box without knowing the size of the geometry
|
||||||
|
if ((!isset($aOutlineResult['aBoundingBox'])) && isset($fLon)) {
|
||||||
|
//
|
||||||
|
if ($this->bIncludePolygonAsPoints) {
|
||||||
|
$sGeometryText = 'POINT('.$fLon.','.$fLat.')';
|
||||||
|
$aOutlineResult['aPolyPoints'] = geometryText2Points($sGeometryText, $fRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
$aBounds = array();
|
||||||
|
$aBounds['minlat'] = $fLat - $fRadius;
|
||||||
|
$aBounds['maxlat'] = $fLat + $fRadius;
|
||||||
|
$aBounds['minlon'] = $fLon - $fRadius;
|
||||||
|
$aBounds['maxlon'] = $fLon + $fRadius;
|
||||||
|
|
||||||
|
$aOutlineResult['aBoundingBox'] = array(
|
||||||
|
(string)$aBounds['minlat'],
|
||||||
|
(string)$aBounds['maxlat'],
|
||||||
|
(string)$aBounds['minlon'],
|
||||||
|
(string)$aBounds['maxlon']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $aOutlineResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
|||||||
@@ -1,36 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
namespace Nominatim;
|
||||||
|
|
||||||
class ReverseGeocode
|
class ReverseGeocode
|
||||||
{
|
{
|
||||||
protected $oDB;
|
protected $oDB;
|
||||||
|
|
||||||
protected $fLat;
|
|
||||||
protected $fLon;
|
|
||||||
protected $iMaxRank = 28;
|
protected $iMaxRank = 28;
|
||||||
|
|
||||||
protected $aLangPrefOrder = array();
|
|
||||||
|
|
||||||
function ReverseGeocode(&$oDB)
|
public function __construct(&$oDB)
|
||||||
{
|
{
|
||||||
$this->oDB =& $oDB;
|
$this->oDB =& $oDB;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLanguagePreference($aLangPref)
|
|
||||||
{
|
|
||||||
$this->aLangPrefOrder = $aLangPref;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLatLon($fLat, $fLon)
|
public function setZoom($iZoom)
|
||||||
{
|
|
||||||
$this->fLat = (float)$fLat;
|
|
||||||
$this->fLon = (float)$fLon;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setRank($iRank)
|
|
||||||
{
|
|
||||||
$this->iMaxRank = $iRank;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setZoom($iZoom)
|
|
||||||
{
|
{
|
||||||
// Zoom to rank, this could probably be calculated but a lookup gives fine control
|
// Zoom to rank, this could probably be calculated but a lookup gives fine control
|
||||||
$aZoomRank = array(
|
$aZoomRank = array(
|
||||||
@@ -58,21 +42,49 @@
|
|||||||
$this->iMaxRank = (isset($iZoom) && isset($aZoomRank[$iZoom]))?$aZoomRank[$iZoom]:28;
|
$this->iMaxRank = (isset($iZoom) && isset($aZoomRank[$iZoom]))?$aZoomRank[$iZoom]:28;
|
||||||
}
|
}
|
||||||
|
|
||||||
function lookup()
|
/**
|
||||||
|
* Find the closest interpolation with the given search diameter.
|
||||||
|
*
|
||||||
|
* @param string $sPointSQL Reverse geocoding point as SQL
|
||||||
|
* @param float $fSearchDiam Search diameter
|
||||||
|
*
|
||||||
|
* @return Record of the interpolation or null.
|
||||||
|
*/
|
||||||
|
protected function lookupInterpolation($sPointSQL, $fSearchDiam)
|
||||||
{
|
{
|
||||||
$sPointSQL = 'ST_SetSRID(ST_Point('.$this->fLon.','.$this->fLat.'),4326)';
|
$sSQL = 'SELECT place_id, parent_place_id, 30 as rank_search,';
|
||||||
|
$sSQL .= ' ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fraction';
|
||||||
|
$sSQL .= ' , ST_Distance(linegeo,'.$sPointSQL.') as distance';
|
||||||
|
$sSQL .= ' FROM location_property_osmline';
|
||||||
|
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
|
||||||
|
$sSQL .= ' and indexed_status = 0 and startnumber is not NULL ';
|
||||||
|
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', linegeo) ASC limit 1';
|
||||||
|
|
||||||
|
return chksql(
|
||||||
|
$this->oDB->getRow($sSQL),
|
||||||
|
"Could not determine closest housenumber on an osm interpolation line."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lookup()
|
||||||
|
* returns { place_id =>, type => '(osm|tiger)' }
|
||||||
|
* fails if no place was found
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
public function lookup($fLat, $fLon, $bDoInterpolation = true)
|
||||||
|
{
|
||||||
|
$sPointSQL = 'ST_SetSRID(ST_Point('.$fLon.','.$fLat.'),4326)';
|
||||||
$iMaxRank = $this->iMaxRank;
|
$iMaxRank = $this->iMaxRank;
|
||||||
$iMaxRank_orig = $this->iMaxRank;
|
|
||||||
|
|
||||||
// Find the nearest point
|
// Find the nearest point
|
||||||
$fSearchDiam = 0.0004;
|
$fSearchDiam = 0.0004;
|
||||||
$iPlaceID = null;
|
$iPlaceID = null;
|
||||||
$aArea = false;
|
|
||||||
$fMaxAreaDistance = 1;
|
$fMaxAreaDistance = 1;
|
||||||
$bIsInUnitedStates = false;
|
$bIsInUnitedStates = false;
|
||||||
$bPlaceIsTiger = false;
|
$bPlaceIsTiger = false;
|
||||||
while(!$iPlaceID && $fSearchDiam < $fMaxAreaDistance)
|
$bPlaceIsLine = false;
|
||||||
{
|
while (!$iPlaceID && $fSearchDiam < $fMaxAreaDistance) {
|
||||||
$fSearchDiam = $fSearchDiam * 2;
|
$fSearchDiam = $fSearchDiam * 2;
|
||||||
|
|
||||||
// If we have to expand the search area by a large amount then we need a larger feature
|
// If we have to expand the search area by a large amount then we need a larger feature
|
||||||
@@ -84,9 +96,30 @@
|
|||||||
if ($fSearchDiam > 0.2 && $iMaxRank > 17) $iMaxRank = 17;
|
if ($fSearchDiam > 0.2 && $iMaxRank > 17) $iMaxRank = 17;
|
||||||
if ($fSearchDiam > 0.1 && $iMaxRank > 18) $iMaxRank = 18;
|
if ($fSearchDiam > 0.1 && $iMaxRank > 18) $iMaxRank = 18;
|
||||||
if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22;
|
if ($fSearchDiam > 0.008 && $iMaxRank > 22) $iMaxRank = 22;
|
||||||
if ($fSearchDiam > 0.001 && $iMaxRank > 26) $iMaxRank = 26;
|
if ($fSearchDiam > 0.001 && $iMaxRank > 26) {
|
||||||
|
// try with interpolations before continuing
|
||||||
|
if ($bDoInterpolation) {
|
||||||
|
// no house found, try with interpolations
|
||||||
|
$aPlaceLine = $this->lookupInterpolation($sPointSQL, $fSearchDiam/2);
|
||||||
|
|
||||||
$sSQL = 'select place_id,parent_place_id,rank_search,calculated_country_code from placex';
|
if ($aPlaceLine) {
|
||||||
|
// interpolation is closer to point than placex house
|
||||||
|
$bPlaceIsLine = true;
|
||||||
|
$aPlace = $aPlaceLine;
|
||||||
|
$iPlaceID = $aPlaceLine['place_id'];
|
||||||
|
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
|
||||||
|
$fFraction = $aPlaceLine['fraction'];
|
||||||
|
$iMaxRank = 30;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// no interpolation found, continue search
|
||||||
|
$iMaxRank = 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sSQL = 'select place_id,parent_place_id,rank_search,country_code';
|
||||||
|
$sSQL .= ' FROM placex';
|
||||||
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, '.$fSearchDiam.')';
|
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, '.$fSearchDiam.')';
|
||||||
$sSQL .= ' and rank_search != 28 and rank_search >= '.$iMaxRank;
|
$sSQL .= ' and rank_search != 28 and rank_search >= '.$iMaxRank;
|
||||||
$sSQL .= ' and (name is not null or housenumber is not null)';
|
$sSQL .= ' and (name is not null or housenumber is not null)';
|
||||||
@@ -96,76 +129,95 @@
|
|||||||
$sSQL .= ' OR ST_DWithin('.$sPointSQL.', centroid, '.$fSearchDiam.'))';
|
$sSQL .= ' OR ST_DWithin('.$sPointSQL.', centroid, '.$fSearchDiam.'))';
|
||||||
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', geometry) ASC limit 1';
|
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', geometry) ASC limit 1';
|
||||||
if (CONST_Debug) var_dump($sSQL);
|
if (CONST_Debug) var_dump($sSQL);
|
||||||
$aPlace = $this->oDB->getRow($sSQL);
|
$aPlace = chksql(
|
||||||
if (PEAR::IsError($aPlace))
|
$this->oDB->getRow($sSQL),
|
||||||
{
|
"Could not determine closest place."
|
||||||
failInternalError("Could not determine closest place.", $sSQL, $aPlace);
|
);
|
||||||
}
|
|
||||||
$iPlaceID = $aPlace['place_id'];
|
$iPlaceID = $aPlace['place_id'];
|
||||||
$iParentPlaceID = $aPlace['parent_place_id'];
|
$iParentPlaceID = $aPlace['parent_place_id'];
|
||||||
$bIsInUnitedStates = ($aPlace['calculated_country_code'] == 'us');
|
$bIsInUnitedStates = ($aPlace['country_code'] == 'us');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a house was found make sure there isn't an interpolation line
|
||||||
|
// that is closer
|
||||||
|
if ($bDoInterpolation && !$bPlaceIsLine && $aPlace && $aPlace['rank_search'] == 30) {
|
||||||
|
// get the distance of the house to the search point
|
||||||
|
$sSQL = 'SELECT ST_distance('.$sPointSQL.', house.geometry)';
|
||||||
|
$sSQL .= ' FROM placex as house WHERE house.place_id='.$iPlaceID;
|
||||||
|
|
||||||
|
$fDistancePlacex = chksql(
|
||||||
|
$this->oDB->getOne($sSQL),
|
||||||
|
"Could not determine distance between searched point and placex house."
|
||||||
|
);
|
||||||
|
|
||||||
|
// look for an interpolation that is closer
|
||||||
|
$aPlaceLine = $this->lookupInterpolation($sPointSQL, $fDistancePlacex);
|
||||||
|
|
||||||
|
if ($aPlaceLine && (float) $aPlaceLine['distance'] < (float) $fDistancePlacex) {
|
||||||
|
// interpolation is closer to point than placex house
|
||||||
|
$bPlaceIsLine = true;
|
||||||
|
$aPlace = $aPlaceLine;
|
||||||
|
$iPlaceID = $aPlaceLine['place_id'];
|
||||||
|
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
|
||||||
|
$fFraction = $aPlaceLine['fraction'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only street found? If it's in the US we can check TIGER data for nearest housenumber
|
// Only street found? If it's in the US we can check TIGER data for nearest housenumber
|
||||||
if ($bIsInUnitedStates && $iMaxRank_orig >= 28 && $iPlaceID && ($aPlace['rank_search'] == 26 || $aPlace['rank_search'] == 27 ))
|
if (CONST_Use_US_Tiger_Data && $bDoInterpolation && $bIsInUnitedStates && $this->iMaxRank >= 28 && $iPlaceID && ($aPlace['rank_search'] == 26 || $aPlace['rank_search'] == 27 )) {
|
||||||
{
|
|
||||||
$fSearchDiam = 0.001;
|
$fSearchDiam = 0.001;
|
||||||
$sSQL = 'SELECT place_id,parent_place_id,30 as rank_search ';
|
$sSQL = 'SELECT place_id,parent_place_id,30 as rank_search, ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fraction';
|
||||||
if (CONST_Debug) { $sSQL .= ', housenumber, ST_distance('.$sPointSQL.', centroid) as distance, st_y(centroid) as lat, st_x(centroid) as lon'; }
|
//if (CONST_Debug) { $sSQL .= ', housenumber, ST_distance('.$sPointSQL.', centroid) as distance, st_y(centroid) as lat, st_x(centroid) as lon'; }
|
||||||
$sSQL .= ' FROM location_property_tiger WHERE parent_place_id = '.$iPlaceID;
|
$sSQL .= ' FROM location_property_tiger WHERE parent_place_id = '.$iPlaceID;
|
||||||
$sSQL .= ' AND ST_DWithin('.$sPointSQL.', centroid, '.$fSearchDiam.')';
|
$sSQL .= ' AND ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')'; //no centroid anymore in Tiger data, now we have lines
|
||||||
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', centroid) ASC limit 1';
|
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', linegeo) ASC limit 1';
|
||||||
|
|
||||||
|
if (CONST_Debug) {
|
||||||
// print all house numbers in the parent (street)
|
|
||||||
if (CONST_Debug)
|
|
||||||
{
|
|
||||||
$sSQL = preg_replace('/limit 1/', 'limit 100', $sSQL);
|
$sSQL = preg_replace('/limit 1/', 'limit 100', $sSQL);
|
||||||
var_dump($sSQL);
|
var_dump($sSQL);
|
||||||
|
|
||||||
$aAllHouses = $this->oDB->getAll($sSQL);
|
$aAllHouses = chksql($this->oDB->getAll($sSQL));
|
||||||
foreach($aAllHouses as $i)
|
foreach ($aAllHouses as $i) {
|
||||||
{
|
|
||||||
echo $i['housenumber'] . ' | ' . $i['distance'] * 1000 . ' | ' . $i['lat'] . ' | ' . $i['lon']. ' | '. "<br>\n";
|
echo $i['housenumber'] . ' | ' . $i['distance'] * 1000 . ' | ' . $i['lat'] . ' | ' . $i['lon']. ' | '. "<br>\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$aPlaceTiger = $this->oDB->getRow($sSQL);
|
$aPlaceTiger = chksql(
|
||||||
if (PEAR::IsError($aPlace))
|
$this->oDB->getRow($sSQL),
|
||||||
{
|
"Could not determine closest Tiger place."
|
||||||
failInternalError("Could not determine closest Tiger place.", $sSQL, $aPlaceTiger);
|
);
|
||||||
}
|
if ($aPlaceTiger) {
|
||||||
if ($aPlaceTiger)
|
if (CONST_Debug) var_dump('found Tiger housenumber', $aPlaceTiger);
|
||||||
{
|
|
||||||
if (CONST_Debug) var_dump('found Tiger place', $aPlaceTiger);
|
|
||||||
$bPlaceIsTiger = true;
|
$bPlaceIsTiger = true;
|
||||||
$aPlace = $aPlaceTiger;
|
$aPlace = $aPlaceTiger;
|
||||||
$iPlaceID = $aPlaceTiger['place_id'];
|
$iPlaceID = $aPlaceTiger['place_id'];
|
||||||
$iParentPlaceID = $aPlaceTiger['parent_place_id']; // the street
|
$iParentPlaceID = $aPlaceTiger['parent_place_id']; // the street
|
||||||
|
$fFraction = $aPlaceTiger['fraction'];
|
||||||
|
$iMaxRank = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The point we found might be too small - use the address to find what it is a child of
|
// The point we found might be too small - use the address to find what it is a child of
|
||||||
if ($iPlaceID && $iMaxRank < 28)
|
if ($iPlaceID && $iMaxRank < 28) {
|
||||||
{
|
if (($aPlace['rank_search'] > 28 || $bPlaceIsTiger || $bPlaceIsLine) && $iParentPlaceID) {
|
||||||
if ($aPlace['rank_search'] > 28 && $iParentPlaceID && !$bPlaceIsTiger)
|
|
||||||
{
|
|
||||||
$iPlaceID = $iParentPlaceID;
|
$iPlaceID = $iParentPlaceID;
|
||||||
|
$bPlaceIsLine = false;
|
||||||
|
$bPlaceIsTiger = false;
|
||||||
}
|
}
|
||||||
$sSQL = "select address_place_id from place_addressline where place_id = $iPlaceID order by abs(cached_rank_address - $iMaxRank) asc,cached_rank_address desc,isaddress desc,distance desc limit 1";
|
$sSQL = 'select address_place_id';
|
||||||
$iPlaceID = $this->oDB->getOne($sSQL);
|
$sSQL .= ' FROM place_addressline';
|
||||||
if (PEAR::IsError($iPlaceID))
|
$sSQL .= " WHERE place_id = $iPlaceID";
|
||||||
{
|
$sSQL .= " ORDER BY abs(cached_rank_address - $iMaxRank) asc,cached_rank_address desc,isaddress desc,distance desc";
|
||||||
failInternalError("Could not get parent for place.", $sSQL, $iPlaceID);
|
$sSQL .= ' LIMIT 1';
|
||||||
}
|
$iPlaceID = chksql($this->oDB->getOne($sSQL), "Could not get parent for place.");
|
||||||
if (!$iPlaceID)
|
if (!$iPlaceID) {
|
||||||
{
|
|
||||||
$iPlaceID = $aPlace['place_id'];
|
$iPlaceID = $aPlace['place_id'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return array(
|
||||||
return array('place_id' => $iPlaceID,
|
'place_id' => $iPlaceID,
|
||||||
'type' => $bPlaceIsTiger ? 'tiger' : 'osm');
|
'type' => $bPlaceIsTiger ? 'tiger' : ($bPlaceIsLine ? 'interpolation' : 'osm'),
|
||||||
|
'fraction' => ($bPlaceIsTiger || $bPlaceIsLine) ? $fFraction : -1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
|||||||
83
lib/cmd.php
83
lib/cmd.php
@@ -1,14 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnknown = false)
|
function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnknown = false)
|
||||||
{
|
{
|
||||||
$aQuick = array();
|
$aQuick = array();
|
||||||
$aCounts = array();
|
$aCounts = array();
|
||||||
|
|
||||||
foreach($aSpec as $aLine)
|
foreach ($aSpec as $aLine) {
|
||||||
{
|
if (is_array($aLine)) {
|
||||||
if (is_array($aLine))
|
|
||||||
{
|
|
||||||
if ($aLine[0]) $aQuick['--'.$aLine[0]] = $aLine;
|
if ($aLine[0]) $aQuick['--'.$aLine[0]] = $aLine;
|
||||||
if ($aLine[1]) $aQuick['-'.$aLine[1]] = $aLine;
|
if ($aLine[1]) $aQuick['-'.$aLine[1]] = $aLine;
|
||||||
$aCounts[$aLine[0]] = 0;
|
$aCounts[$aLine[0]] = 0;
|
||||||
@@ -18,34 +17,29 @@
|
|||||||
$aResult = array();
|
$aResult = array();
|
||||||
$bUnknown = false;
|
$bUnknown = false;
|
||||||
$iSize = sizeof($aArg);
|
$iSize = sizeof($aArg);
|
||||||
for ($i = 1; $i < $iSize; $i++)
|
for ($i = 1; $i < $iSize; $i++) {
|
||||||
{
|
if (isset($aQuick[$aArg[$i]])) {
|
||||||
if (isset($aQuick[$aArg[$i]]))
|
|
||||||
{
|
|
||||||
$aLine = $aQuick[$aArg[$i]];
|
$aLine = $aQuick[$aArg[$i]];
|
||||||
$aCounts[$aLine[0]]++;
|
$aCounts[$aLine[0]]++;
|
||||||
$xVal = null;
|
$xVal = null;
|
||||||
if ($aLine[4] == $aLine[5])
|
if ($aLine[4] == $aLine[5]) {
|
||||||
{
|
if ($aLine[4]) {
|
||||||
if ($aLine[4])
|
|
||||||
{
|
|
||||||
$xVal = array();
|
$xVal = array();
|
||||||
for($n = $aLine[4]; $i < $iSize && $n; $n--)
|
for ($n = $aLine[4]; $i < $iSize && $n; $n--) {
|
||||||
{
|
|
||||||
$i++;
|
$i++;
|
||||||
if ($i >= $iSize || $aArg[$i][0] == '-') showUsage($aSpec, $bExitOnError, 'Parameter of \''.$aLine[0].'\' is missing');
|
if ($i >= $iSize || $aArg[$i][0] == '-') showUsage($aSpec, $bExitOnError, 'Parameter of \''.$aLine[0].'\' is missing');
|
||||||
|
|
||||||
switch ($aLine[6])
|
switch ($aLine[6]) {
|
||||||
{
|
|
||||||
case 'realpath':
|
case 'realpath':
|
||||||
$xVal[] = realpath($aArg[$i]);
|
$xVal[] = realpath($aArg[$i]);
|
||||||
break;
|
break;
|
||||||
case 'realdir':
|
case 'realdir':
|
||||||
$sPath = realpath(dirname($aArg[$i]));
|
$sPath = realpath(dirname($aArg[$i]));
|
||||||
if ($sPath)
|
if ($sPath) {
|
||||||
$xVal[] = $sPath . '/' . basename($aArg[$i]);
|
$xVal[] = $sPath . '/' . basename($aArg[$i]);
|
||||||
else
|
} else {
|
||||||
$xVal[] = $sPath;
|
$xVal[] = $sPath;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'bool':
|
case 'bool':
|
||||||
$xVal[] = (bool)$aArg[$i];
|
$xVal[] = (bool)$aArg[$i];
|
||||||
@@ -62,29 +56,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($aLine[4] == 1) $xVal = $xVal[0];
|
if ($aLine[4] == 1) $xVal = $xVal[0];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$xVal = true;
|
$xVal = true;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
fail('Variable numbers of params not yet supported');
|
fail('Variable numbers of params not yet supported');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($aLine[3] > 1)
|
if ($aLine[3] > 1) {
|
||||||
{
|
|
||||||
if (!array_key_exists($aLine[0], $aResult)) $aResult[$aLine[0]] = array();
|
if (!array_key_exists($aLine[0], $aResult)) $aResult[$aLine[0]] = array();
|
||||||
$aResult[$aLine[0]][] = $xVal;
|
$aResult[$aLine[0]][] = $xVal;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aResult[$aLine[0]] = $xVal;
|
$aResult[$aLine[0]] = $xVal;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$bUnknown = $aArg[$i];
|
$bUnknown = $aArg[$i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,14 +77,11 @@
|
|||||||
if (array_key_exists('help', $aResult)) showUsage($aSpec);
|
if (array_key_exists('help', $aResult)) showUsage($aSpec);
|
||||||
if ($bUnknown && $bExitOnUnknown) showUsage($aSpec, $bExitOnError, 'Unknown option \''.$bUnknown.'\'');
|
if ($bUnknown && $bExitOnUnknown) showUsage($aSpec, $bExitOnError, 'Unknown option \''.$bUnknown.'\'');
|
||||||
|
|
||||||
foreach($aSpec as $aLine)
|
foreach ($aSpec as $aLine) {
|
||||||
{
|
if (is_array($aLine)) {
|
||||||
if (is_array($aLine))
|
|
||||||
{
|
|
||||||
if ($aCounts[$aLine[0]] < $aLine[2]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is missing');
|
if ($aCounts[$aLine[0]] < $aLine[2]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is missing');
|
||||||
if ($aCounts[$aLine[0]] > $aLine[3]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is pressent too many times');
|
if ($aCounts[$aLine[0]] > $aLine[3]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is pressent too many times');
|
||||||
switch ($aLine[6])
|
switch ($aLine[6]) {
|
||||||
{
|
|
||||||
case 'bool':
|
case 'bool':
|
||||||
if (!array_key_exists($aLine[0], $aResult))
|
if (!array_key_exists($aLine[0], $aResult))
|
||||||
$aResult[$aLine[0]] = false;
|
$aResult[$aLine[0]] = false;
|
||||||
@@ -112,20 +94,16 @@
|
|||||||
|
|
||||||
function showUsage($aSpec, $bExit = false, $sError = false)
|
function showUsage($aSpec, $bExit = false, $sError = false)
|
||||||
{
|
{
|
||||||
if ($sError)
|
if ($sError) {
|
||||||
{
|
|
||||||
echo basename($_SERVER['argv'][0]).': '.$sError."\n";
|
echo basename($_SERVER['argv'][0]).': '.$sError."\n";
|
||||||
echo 'Try `'.basename($_SERVER['argv'][0]).' --help` for more information.'."\n";
|
echo 'Try `'.basename($_SERVER['argv'][0]).' --help` for more information.'."\n";
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
echo "Usage: ".basename($_SERVER['argv'][0])."\n";
|
echo "Usage: ".basename($_SERVER['argv'][0])."\n";
|
||||||
$bFirst = true;
|
$bFirst = true;
|
||||||
foreach($aSpec as $aLine)
|
foreach ($aSpec as $aLine) {
|
||||||
{
|
if (is_array($aLine)) {
|
||||||
if (is_array($aLine))
|
if ($bFirst) {
|
||||||
{
|
|
||||||
if ($bFirst)
|
|
||||||
{
|
|
||||||
$bFirst = false;
|
$bFirst = false;
|
||||||
echo "\n";
|
echo "\n";
|
||||||
}
|
}
|
||||||
@@ -134,12 +112,19 @@
|
|||||||
if ($aLine[0]) $aNames[] = '--'.$aLine[0];
|
if ($aLine[0]) $aNames[] = '--'.$aLine[0];
|
||||||
$sName = join(', ', $aNames);
|
$sName = join(', ', $aNames);
|
||||||
echo ' '.$sName.str_repeat(' ', 30-strlen($sName)).$aLine[7]."\n";
|
echo ' '.$sName.str_repeat(' ', 30-strlen($sName)).$aLine[7]."\n";
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
echo $aLine."\n";
|
echo $aLine."\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
echo "\n";
|
echo "\n";
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function chksql($oSql, $sMsg = false)
|
||||||
|
{
|
||||||
|
if (PEAR::isError($oSql)) {
|
||||||
|
fail($sMsg || $oSql->getMessage(), $oSql->userinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $oSql;
|
||||||
|
}
|
||||||
|
|||||||
26
lib/db.php
26
lib/db.php
@@ -1,16 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once('DB.php');
|
require_once('DB.php');
|
||||||
|
|
||||||
|
|
||||||
function &getDB($bNew = false, $bPersistent = false)
|
function &getDB($bNew = false, $bPersistent = false)
|
||||||
{
|
{
|
||||||
// Get the database object
|
// Get the database object
|
||||||
$oDB =& DB::connect(CONST_Database_DSN.($bNew?'?new_link=true':''), $bPersistent);
|
$oDB = chksql(
|
||||||
if (PEAR::IsError($oDB))
|
DB::connect(CONST_Database_DSN.($bNew?'?new_link=true':''), $bPersistent),
|
||||||
{
|
"Failed to establish database connection"
|
||||||
var_dump(CONST_Database_DSN);
|
);
|
||||||
var_Dump($oDB);
|
|
||||||
fail($oDB->getMessage());
|
|
||||||
}
|
|
||||||
$oDB->setFetchMode(DB_FETCHMODE_ASSOC);
|
$oDB->setFetchMode(DB_FETCHMODE_ASSOC);
|
||||||
$oDB->query("SET DateStyle TO 'sql,european'");
|
$oDB->query("SET DateStyle TO 'sql,european'");
|
||||||
$oDB->query("SET client_encoding TO 'utf-8'");
|
$oDB->query("SET client_encoding TO 'utf-8'");
|
||||||
@@ -24,3 +23,16 @@
|
|||||||
return "'".pg_escape_string($s)."'";
|
return "'".pg_escape_string($s)."'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPostgresVersion(&$oDB)
|
||||||
|
{
|
||||||
|
$sVersionString = $oDB->getOne('select version()');
|
||||||
|
preg_match('#PostgreSQL ([0-9]+)[.]([0-9]+)[^0-9]#', $sVersionString, $aMatches);
|
||||||
|
return (float) ($aMatches[1].'.'.$aMatches[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPostgisVersion(&$oDB)
|
||||||
|
{
|
||||||
|
$sVersionString = $oDB->getOne('select postgis_full_version()');
|
||||||
|
preg_match('#POSTGIS="([0-9]+)[.]([0-9]+)[.]([0-9]+)( r([0-9]+))?"#', $sVersionString, $aMatches);
|
||||||
|
return (float) ($aMatches[1].'.'.$aMatches[2]);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
if (file_exists(getenv('NOMINATIM_SETTINGS')))
|
|
||||||
{
|
|
||||||
require_once(getenv('NOMINATIM_SETTINGS'));
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once('init.php');
|
require_once('init.php');
|
||||||
require_once('cmd.php');
|
require_once('cmd.php');
|
||||||
|
|||||||
@@ -1,64 +1,100 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once('init.php');
|
|
||||||
|
|
||||||
if (CONST_NoAccessControl)
|
require_once('init.php');
|
||||||
|
require_once('ParameterParser.php');
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
*
|
||||||
|
* Error handling functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
function chksql($oSql, $sMsg = "Database request failed")
|
||||||
{
|
{
|
||||||
|
if (!PEAR::isError($oSql)) return $oSql;
|
||||||
|
|
||||||
|
header('HTTP/1.0 500 Internal Server Error');
|
||||||
|
header('Content-type: text/html; charset=utf-8');
|
||||||
|
|
||||||
|
$sSqlError = $oSql->getMessage();
|
||||||
|
|
||||||
|
echo <<<INTERNALFAIL
|
||||||
|
<html>
|
||||||
|
<head><title>Internal Server Error</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Internal Server Error</h1>
|
||||||
|
<p>Nominatim has encountered an internal error while accessing the database.
|
||||||
|
This may happen because the database is broken or because of a bug in
|
||||||
|
the software. If you think it is a bug, feel free to report
|
||||||
|
it over on <a href="https://github.com/openstreetmap/Nominatim/issues">
|
||||||
|
Github</a>. Please include the URL that caused the problem and the
|
||||||
|
complete error details below.</p>
|
||||||
|
<p><b>Message:</b> $sMsg</p>
|
||||||
|
<p><b>SQL Error:</b> $sSqlError</p>
|
||||||
|
<p><b>Details:</b> <pre>
|
||||||
|
INTERNALFAIL;
|
||||||
|
|
||||||
|
if (CONST_Debug) {
|
||||||
|
var_dump($oSql);
|
||||||
|
} else {
|
||||||
|
echo "<pre>\n".$oSql->getUserInfo()."</pre>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "</pre></p></body></html>";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function failInternalError($sError, $sSQL = false, $vDumpVar = false)
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 500 Internal Server Error');
|
||||||
|
header('Content-type: text/html; charset=utf-8');
|
||||||
|
echo "<html><body><h1>Internal Server Error</h1>";
|
||||||
|
echo '<p>Nominatim has encountered an internal error while processing your request. This is most likely because of a bug in the software.</p>';
|
||||||
|
echo "<p><b>Details:</b> ".$sError,"</p>";
|
||||||
|
echo '<p>Feel free to file an issue on <a href="https://github.com/openstreetmap/Nominatim/issues">Github</a>. ';
|
||||||
|
echo 'Please include the error message above and the URL you used.</p>';
|
||||||
|
if (CONST_Debug) {
|
||||||
|
echo "<hr><h2>Debugging Information</h2><br>";
|
||||||
|
if ($sSQL) {
|
||||||
|
echo "<h3>SQL query</h3><code>".$sSQL."</code>";
|
||||||
|
}
|
||||||
|
if ($vDumpVar) {
|
||||||
|
echo "<h3>Result</h3> <code>";
|
||||||
|
var_dump($vDumpVar);
|
||||||
|
echo "</code>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo "\n</body></html>\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function userError($sError)
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 400 Bad Request');
|
||||||
|
header('Content-type: text/html; charset=utf-8');
|
||||||
|
echo "<html><body><h1>Bad Request</h1>";
|
||||||
|
echo '<p>Nominatim has encountered an error with your request.</p>';
|
||||||
|
echo "<p><b>Details:</b> ".$sError."</p>";
|
||||||
|
echo '<p>If you feel this error is incorrect feel file an issue on <a href="https://github.com/openstreetmap/Nominatim/issues">Github</a>. ';
|
||||||
|
echo 'Please include the error message above and the URL you used.</p>';
|
||||||
|
echo "\n</body></html>\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* HTTP Reply header setup
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (CONST_NoAccessControl) {
|
||||||
header("Access-Control-Allow-Origin: *");
|
header("Access-Control-Allow-Origin: *");
|
||||||
header("Access-Control-Allow-Methods: OPTIONS,GET");
|
header("Access-Control-Allow-Methods: OPTIONS,GET");
|
||||||
if (!empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
|
if (!empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
|
||||||
{
|
|
||||||
header("Access-Control-Allow-Headers: ".$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
|
header("Access-Control-Allow-Headers: ".$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') exit;
|
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') exit;
|
||||||
|
|
||||||
if (CONST_ClosedForIndexing && strpos(CONST_ClosedForIndexingExceptionIPs, ','.$_SERVER["REMOTE_ADDR"].',') === false)
|
if (CONST_Debug) header('Content-type: text/html; charset=utf-8');
|
||||||
{
|
|
||||||
echo "Closed for re-indexing...";
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$aBucketKeys = array();
|
|
||||||
|
|
||||||
if (isset($_SERVER["HTTP_REFERER"])) $aBucketKeys[] = str_replace('www.','',strtolower(parse_url($_SERVER["HTTP_REFERER"], PHP_URL_HOST)));
|
|
||||||
if (isset($_SERVER["REMOTE_ADDR"])) $aBucketKeys[] = $_SERVER["REMOTE_ADDR"];
|
|
||||||
if (isset($_GET["email"])) $aBucketKeys[] = $_GET["email"];
|
|
||||||
|
|
||||||
$fBucketVal = doBucket($aBucketKeys,
|
|
||||||
(defined('CONST_ConnectionBucket_PageType')?constant('CONST_ConnectionBucket_Cost_'.CONST_ConnectionBucket_PageType):1) + user_busy_cost(),
|
|
||||||
CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit);
|
|
||||||
|
|
||||||
if ($fBucketVal > CONST_ConnectionBucket_WaitLimit && $fBucketVal < CONST_ConnectionBucket_BlockLimit)
|
|
||||||
{
|
|
||||||
$m = getBucketMemcache();
|
|
||||||
$iCurrentSleeping = $m->increment('sleepCounter');
|
|
||||||
if (false === $iCurrentSleeping)
|
|
||||||
{
|
|
||||||
$m->add('sleepCounter', 0);
|
|
||||||
$iCurrentSleeping = $m->increment('sleepCounter');
|
|
||||||
}
|
|
||||||
if ($iCurrentSleeping >= CONST_ConnectionBucket_MaxSleeping || isBucketSleeping($aBucketKeys))
|
|
||||||
{
|
|
||||||
// Too many threads sleeping already. This becomes a hard block.
|
|
||||||
$fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_BlockLimit, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setBucketSleeping($aBucketKeys, true);
|
|
||||||
sleep(($fBucketVal - CONST_ConnectionBucket_WaitLimit)/CONST_ConnectionBucket_LeakRate);
|
|
||||||
$fBucketVal = doBucket($aBucketKeys, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_LeakRate, CONST_ConnectionBucket_BlockLimit);
|
|
||||||
setBucketSleeping($aBucketKeys, false);
|
|
||||||
}
|
|
||||||
$m->decrement('sleepCounter');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos(CONST_BlockedIPs, ','.$_SERVER["REMOTE_ADDR"].',') !== false || $fBucketVal >= CONST_ConnectionBucket_BlockLimit)
|
|
||||||
{
|
|
||||||
header("HTTP/1.0 429 Too Many Requests");
|
|
||||||
echo "Your IP has been blocked. \n";
|
|
||||||
echo CONST_BlockMessage;
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-type: text/html; charset=utf-8');
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
@define('CONST_BasePath', dirname(dirname(__FILE__)));
|
|
||||||
|
|
||||||
require_once(CONST_BasePath.'/settings/settings.php');
|
|
||||||
require_once(CONST_BasePath.'/lib/lib.php');
|
require_once(CONST_BasePath.'/lib/lib.php');
|
||||||
require_once(CONST_BasePath.'/lib/leakybucket.php');
|
|
||||||
require_once(CONST_BasePath.'/lib/db.php');
|
require_once(CONST_BasePath.'/lib/db.php');
|
||||||
|
|
||||||
if (get_magic_quotes_gpc())
|
if (get_magic_quotes_gpc()) {
|
||||||
{
|
|
||||||
echo "Please disable magic quotes in your php.ini configuration\n";
|
echo "Please disable magic quotes in your php.ini configuration\n";
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,168 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
function getBucketMemcache()
|
|
||||||
{
|
|
||||||
static $m;
|
|
||||||
|
|
||||||
if (!CONST_ConnectionBucket_MemcacheServerAddress) return null;
|
|
||||||
if (!isset($m))
|
|
||||||
{
|
|
||||||
$m = new Memcached();
|
|
||||||
$m->addServer(CONST_ConnectionBucket_MemcacheServerAddress, CONST_ConnectionBucket_MemcacheServerPort);
|
|
||||||
}
|
|
||||||
return $m;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doBucket($asKey, $iRequestCost, $iLeakPerSecond, $iThreshold)
|
|
||||||
{
|
|
||||||
$m = getBucketMemcache();
|
|
||||||
if (!$m) return 0;
|
|
||||||
|
|
||||||
$iMaxVal = 0;
|
|
||||||
$t = time();
|
|
||||||
|
|
||||||
foreach($asKey as $sKey)
|
|
||||||
{
|
|
||||||
$aCurrentBlock = $m->get($sKey);
|
|
||||||
if (!$aCurrentBlock)
|
|
||||||
{
|
|
||||||
$aCurrentBlock = array($iRequestCost, $t, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// add RequestCost
|
|
||||||
// remove leak * the time since the last request
|
|
||||||
$aCurrentBlock[0] += $iRequestCost - ($t - $aCurrentBlock[1])*$iLeakPerSecond;
|
|
||||||
$aCurrentBlock[1] = $t;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($aCurrentBlock[0] <= 0)
|
|
||||||
{
|
|
||||||
$m->delete($sKey);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we have hit the threshold stop and record this to the block list
|
|
||||||
if ($aCurrentBlock[0] >= $iThreshold)
|
|
||||||
{
|
|
||||||
$aCurrentBlock[0] = $iThreshold;
|
|
||||||
|
|
||||||
// Make up to 10 attempts to record this to memcache (with locking to prevent conflicts)
|
|
||||||
$i = 10;
|
|
||||||
for($i = 0; $i < 10; $i++)
|
|
||||||
{
|
|
||||||
$aBlockedList = $m->get('blockedList', null, $hCasToken);
|
|
||||||
if (!$aBlockedList)
|
|
||||||
{
|
|
||||||
$aBlockedList = array();
|
|
||||||
$m->add('blockedList', $aBlockedList);
|
|
||||||
$aBlockedList = $m->get('blockedList', null, $hCasToken);
|
|
||||||
}
|
|
||||||
if (!isset($aBlockedList[$sKey]))
|
|
||||||
{
|
|
||||||
$aBlockedList[$sKey] = array(1, $t);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$aBlockedList[$sKey][0]++;
|
|
||||||
$aBlockedList[$sKey][1] = $t;
|
|
||||||
}
|
|
||||||
if (sizeof($aBlockedList) > CONST_ConnectionBucket_MaxBlockList)
|
|
||||||
{
|
|
||||||
uasort($aBlockedList, 'byValue1');
|
|
||||||
$aBlockedList = array_slice($aBlockedList, 0, CONST_ConnectionBucket_MaxBlockList);
|
|
||||||
}
|
|
||||||
$x = $m->cas($hCasToken, 'blockedList', $aBlockedList);
|
|
||||||
if ($x) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Only keep in memcache until the time it would have expired (to avoid clutering memcache)
|
|
||||||
$m->set($sKey, $aCurrentBlock, $t + 1 + $aCurrentBlock[0]/$iLeakPerSecond);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucket result in the largest bucket we find
|
|
||||||
$iMaxVal = max($iMaxVal, $aCurrentBlock[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $iMaxVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isBucketSleeping($asKey)
|
|
||||||
{
|
|
||||||
$m = getBucketMemcache();
|
|
||||||
if (!$m) return false;
|
|
||||||
|
|
||||||
foreach($asKey as $sKey)
|
|
||||||
{
|
|
||||||
$aCurrentBlock = $m->get($sKey);
|
|
||||||
if ($aCurrentBlock[2]) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setBucketSleeping($asKey, $bVal)
|
|
||||||
{
|
|
||||||
$m = getBucketMemcache();
|
|
||||||
if (!$m) return false;
|
|
||||||
|
|
||||||
$iMaxVal = 0;
|
|
||||||
$t = time();
|
|
||||||
|
|
||||||
foreach($asKey as $sKey)
|
|
||||||
{
|
|
||||||
$aCurrentBlock = $m->get($sKey);
|
|
||||||
$aCurrentBlock[2] = $bVal;
|
|
||||||
$m->set($sKey, $aCurrentBlock, $t + 1 + $aCurrentBlock[0]/CONST_ConnectionBucket_LeakRate);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function byValue1($a, $b)
|
|
||||||
{
|
|
||||||
if ($a[1] == $b[1])
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ($a[1] > $b[1]) ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function byLastBlockTime($a, $b)
|
|
||||||
{
|
|
||||||
if ($a['lastBlockTimestamp'] == $b['lastBlockTimestamp'])
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ($a['lastBlockTimestamp'] > $b['lastBlockTimestamp']) ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBucketBlocks()
|
|
||||||
{
|
|
||||||
$m = getBucketMemcache();
|
|
||||||
if (!$m) return null;
|
|
||||||
$t = time();
|
|
||||||
$aBlockedList = $m->get('blockedList', null, $hCasToken);
|
|
||||||
if (!$aBlockedList) $aBlockedList = array();
|
|
||||||
foreach($aBlockedList as $sKey => $aDetails)
|
|
||||||
{
|
|
||||||
$aCurrentBlock = $m->get($sKey);
|
|
||||||
if (!$aCurrentBlock) $aCurrentBlock = array(0, $t);
|
|
||||||
$iCurrentBucketSize = max(0, $aCurrentBlock[0] - ($t - $aCurrentBlock[1])*CONST_ConnectionBucket_LeakRate);
|
|
||||||
$aBlockedList[$sKey] = array(
|
|
||||||
'totalBlocks' => $aDetails[0],
|
|
||||||
'lastBlockTimestamp' => $aDetails[1],
|
|
||||||
'isSleeping' => (isset($aCurrentBlock[2])?$aCurrentBlock[2]:false),
|
|
||||||
'currentBucketSize' => $iCurrentBucketSize,
|
|
||||||
'currentlyBlocked' => $iCurrentBucketSize + (CONST_ConnectionBucket_Cost_Reverse) >= CONST_ConnectionBucket_BlockLimit,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
uasort($aBlockedList, 'byLastBlockTime');
|
|
||||||
return $aBlockedList;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearBucketBlocks()
|
|
||||||
{
|
|
||||||
$m = getBucketMemcache();
|
|
||||||
if (!$m) return false;
|
|
||||||
$m->delete('blockedList');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
1194
lib/lib.php
1194
lib/lib.php
File diff suppressed because it is too large
Load Diff
92
lib/log.php
92
lib/log.php
@@ -1,70 +1,58 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
function logStart(&$oDB, $sType = '', $sQuery = '', $aLanguageList = array())
|
function logStart(&$oDB, $sType = '', $sQuery = '', $aLanguageList = array())
|
||||||
{
|
{
|
||||||
$aStartTime = explode('.',microtime(true));
|
$fStartTime = microtime(true);
|
||||||
|
$aStartTime = explode('.', $fStartTime);
|
||||||
if (!isset($aStartTime[1])) $aStartTime[1] = '0';
|
if (!isset($aStartTime[1])) $aStartTime[1] = '0';
|
||||||
|
|
||||||
$sOutputFormat = '';
|
$sOutputFormat = '';
|
||||||
if (isset($_GET['format'])) $sOutputFormat = $_GET['format'];
|
if (isset($_GET['format'])) $sOutputFormat = $_GET['format'];
|
||||||
|
|
||||||
|
if ($sType == 'reverse') {
|
||||||
|
$sOutQuery = (isset($_GET['lat'])?$_GET['lat']:'').'/';
|
||||||
|
if (isset($_GET['lon'])) $sOutQuery .= $_GET['lon'];
|
||||||
|
if (isset($_GET['zoom'])) $sOutQuery .= '/'.$_GET['zoom'];
|
||||||
|
} else {
|
||||||
|
$sOutQuery = $sQuery;
|
||||||
|
}
|
||||||
|
|
||||||
$hLog = array(
|
$hLog = array(
|
||||||
date('Y-m-d H:i:s', $aStartTime[0]).'.'.$aStartTime[1],
|
date('Y-m-d H:i:s', $aStartTime[0]).'.'.$aStartTime[1],
|
||||||
$_SERVER["REMOTE_ADDR"],
|
$_SERVER["REMOTE_ADDR"],
|
||||||
$_SERVER['QUERY_STRING'],
|
$_SERVER['QUERY_STRING'],
|
||||||
$sQuery
|
$sOutQuery,
|
||||||
|
$sType,
|
||||||
|
$fStartTime
|
||||||
);
|
);
|
||||||
|
|
||||||
if (CONST_Log_DB)
|
if (CONST_Log_DB) {
|
||||||
{
|
if (isset($_GET['email']))
|
||||||
// Log
|
$sUserAgent = $_GET['email'];
|
||||||
if ($sType == 'search')
|
elseif (isset($_SERVER['HTTP_REFERER']))
|
||||||
{
|
$sUserAgent = $_SERVER['HTTP_REFERER'];
|
||||||
$oDB->query('insert into query_log values ('.getDBQuoted($hLog[0]).','.getDBQuoted($hLog[3]).','.getDBQuoted($hLog[1]).')');
|
elseif (isset($_SERVER['HTTP_USER_AGENT']))
|
||||||
}
|
$sUserAgent = $_SERVER['HTTP_USER_AGENT'];
|
||||||
|
else $sUserAgent = '';
|
||||||
$sSQL = 'insert into new_query_log (type,starttime,query,ipaddress,useragent,language,format)';
|
$sSQL = 'insert into new_query_log (type,starttime,query,ipaddress,useragent,language,format,searchterm)';
|
||||||
$sSQL .= ' values ('.getDBQuoted($sType).','.getDBQuoted($hLog[0]).','.getDBQuoted($hLog[2]);
|
$sSQL .= ' values ('.getDBQuoted($sType).','.getDBQuoted($hLog[0]).','.getDBQuoted($hLog[2]);
|
||||||
$sSQL .= ','.getDBQuoted($hLog[1]).','.getDBQuoted($_SERVER['HTTP_USER_AGENT']).','.getDBQuoted(join(',',$aLanguageList)).','.getDBQuoted($sOutputFormat).')';
|
$sSQL .= ','.getDBQuoted($hLog[1]).','.getDBQuoted($sUserAgent).','.getDBQuoted(join(',', $aLanguageList)).','.getDBQuoted($sOutputFormat).','.getDBQuoted($hLog[3]).')';
|
||||||
$oDB->query($sSQL);
|
$oDB->query($sSQL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CONST_Log_File && CONST_Log_File_ReverseLog != '')
|
|
||||||
{
|
|
||||||
if ($sType == 'reverse')
|
|
||||||
{
|
|
||||||
$aStartTime = explode('.',$hLog[0]);
|
|
||||||
file_put_contents(CONST_Log_File_ReverseLog,
|
|
||||||
$aStartTime[0].','.$aStartTime[1].','.
|
|
||||||
php_uname('n').','.
|
|
||||||
'"'.addslashes(isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:'').'",'.
|
|
||||||
'"'.addslashes($hLog[1]).'",'.
|
|
||||||
$_GET['lat'].','.
|
|
||||||
$_GET['lon'].','.
|
|
||||||
$_GET['zoom'].','.
|
|
||||||
'"'.addslashes($_SERVER['HTTP_USER_AGENT']).'",'.
|
|
||||||
'"'.addslashes($sOutputFormat).'"'."\n",
|
|
||||||
FILE_APPEND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $hLog;
|
return $hLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
function logEnd(&$oDB, $hLog, $iNumResults)
|
function logEnd(&$oDB, $hLog, $iNumResults)
|
||||||
{
|
{
|
||||||
$aEndTime = explode('.',microtime(true));
|
$fEndTime = microtime(true);
|
||||||
|
|
||||||
|
if (CONST_Log_DB) {
|
||||||
|
$aEndTime = explode('.', $fEndTime);
|
||||||
if (!$aEndTime[1]) $aEndTime[1] = '0';
|
if (!$aEndTime[1]) $aEndTime[1] = '0';
|
||||||
$sEndTime = date('Y-m-d H:i:s', $aEndTime[0]).'.'.$aEndTime[1];
|
$sEndTime = date('Y-m-d H:i:s', $aEndTime[0]).'.'.$aEndTime[1];
|
||||||
|
|
||||||
if (CONST_Log_DB)
|
|
||||||
{
|
|
||||||
$sSQL = 'update query_log set endtime = '.getDBQuoted($sEndTime).', results = '.$iNumResults;
|
|
||||||
$sSQL .= ' where starttime = '.getDBQuoted($hLog[0]);
|
|
||||||
$sSQL .= ' and ipaddress = '.getDBQuoted($hLog[1]);
|
|
||||||
$sSQL .= ' and query = '.getDBQuoted($hLog[3]);
|
|
||||||
$oDB->query($sSQL);
|
|
||||||
|
|
||||||
$sSQL = 'update new_query_log set endtime = '.getDBQuoted($sEndTime).', results = '.$iNumResults;
|
$sSQL = 'update new_query_log set endtime = '.getDBQuoted($sEndTime).', results = '.$iNumResults;
|
||||||
$sSQL .= ' where starttime = '.getDBQuoted($hLog[0]);
|
$sSQL .= ' where starttime = '.getDBQuoted($hLog[0]);
|
||||||
$sSQL .= ' and ipaddress = '.getDBQuoted($hLog[1]);
|
$sSQL .= ' and ipaddress = '.getDBQuoted($hLog[1]);
|
||||||
@@ -72,19 +60,15 @@
|
|||||||
$oDB->query($sSQL);
|
$oDB->query($sSQL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CONST_Log_File && CONST_Log_File_SearchLog != '')
|
if (CONST_Log_File) {
|
||||||
{
|
$aOutdata = sprintf(
|
||||||
$aStartTime = explode('.',$hLog[0]);
|
"[%s] %.4f %d %s \"%s\"\n",
|
||||||
file_put_contents(CONST_Log_File_SearchLog,
|
$hLog[0],
|
||||||
$aStartTime[0].','.$aStartTime[1].','.
|
$fEndTime-$hLog[5],
|
||||||
php_uname('n').','.
|
$iNumResults,
|
||||||
'"'.addslashes(isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:'').'",'.
|
$hLog[4],
|
||||||
'"'.addslashes($hLog[1]).'",'.
|
$hLog[2]
|
||||||
'"'.addslashes($hLog[3]).'",'.
|
);
|
||||||
'"'.addslashes($_SERVER['HTTP_USER_AGENT']).'",'.
|
file_put_contents(CONST_Log_File, $aOutdata, FILE_APPEND | LOCK_EX);
|
||||||
'"'.addslashes((isset($_GET['format']))?$_GET['format']:'').'",'.
|
|
||||||
$iNumResults."\n",
|
|
||||||
FILE_APPEND);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
41
lib/output.php
Normal file
41
lib/output.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
function formatOSMType($sType, $bIncludeExternal = true)
|
||||||
|
{
|
||||||
|
if ($sType == 'N') return 'node';
|
||||||
|
if ($sType == 'W') return 'way';
|
||||||
|
if ($sType == 'R') return 'relation';
|
||||||
|
|
||||||
|
if (!$bIncludeExternal) return '';
|
||||||
|
|
||||||
|
if ($sType == 'T') return 'way';
|
||||||
|
if ($sType == 'I') return 'way';
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function osmLink($aFeature, $sRefText = false)
|
||||||
|
{
|
||||||
|
$sOSMType = formatOSMType($aFeature['osm_type'], false);
|
||||||
|
if ($sOSMType) {
|
||||||
|
return '<a href="//www.openstreetmap.org/'.$sOSMType.'/'.$aFeature['osm_id'].'">'.$sOSMType.' '.($sRefText?$sRefText:$aFeature['osm_id']).'</a>';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function wikipediaLink($aFeature)
|
||||||
|
{
|
||||||
|
if ($aFeature['wikipedia']) {
|
||||||
|
list($sLanguage, $sArticle) = explode(':', $aFeature['wikipedia']);
|
||||||
|
return '<a href="https://'.$sLanguage.'.wikipedia.org/wiki/'.urlencode($sArticle).'" target="_blank">'.$aFeature['wikipedia'].'</a>';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function detailsLink($aFeature, $sTitle = false)
|
||||||
|
{
|
||||||
|
if (!$aFeature['place_id']) return '';
|
||||||
|
|
||||||
|
return '<a href="details.php?place_id='.$aFeature['place_id'].'">'.($sTitle?$sTitle:$aFeature['place_id']).'</a>';
|
||||||
|
}
|
||||||
@@ -13,12 +13,13 @@
|
|||||||
<form class="form-inline" role="search" accept-charset="UTF-8" action="<?php echo CONST_Website_BaseURL; ?>reverse.php">
|
<form class="form-inline" role="search" accept-charset="UTF-8" action="<?php echo CONST_Website_BaseURL; ?>reverse.php">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input name="format" type="hidden" value="html">
|
<input name="format" type="hidden" value="html">
|
||||||
<input name="lat" type="text" class="form-control input-sm" placeholder="latitude" value="<?php echo htmlspecialchars($_GET['lat']); ?>" >
|
<input name="lat" type="text" class="form-control input-sm" placeholder="latitude" value="<?php echo $fLat; ?>" >
|
||||||
<input name="lon" type="text" class="form-control input-sm" placeholder="longitude" value="<?php echo htmlspecialchars($_GET['lon']); ?>" >
|
<span id="switch-coords"><></span>
|
||||||
|
<input name="lon" type="text" class="form-control input-sm" placeholder="longitude" value="<?php echo $fLon; ?>" >
|
||||||
max zoom
|
max zoom
|
||||||
|
|
||||||
<select name="zoom" class="form-control input-sm" value="<?php echo htmlspecialchars($_GET['zoom']); ?>">
|
<select name="zoom" class="form-control input-sm">
|
||||||
<option value="" <?php echo $_GET['zoom']==''?'selected':'' ?> >--</option>
|
<option value="" <?php if ($iZoom === false) echo 'selected="selected"' ?> >--</option>
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$aZoomLevels = array(
|
$aZoomLevels = array(
|
||||||
@@ -48,8 +49,8 @@
|
|||||||
|
|
||||||
foreach($aZoomLevels as $iZoomLevel => $sLabel)
|
foreach($aZoomLevels as $iZoomLevel => $sLabel)
|
||||||
{
|
{
|
||||||
$bSel = isset($_GET['zoom']) && ($_GET['zoom'] == (string)$iZoomLevel);
|
$bSel = $iZoom === $iZoomLevel;
|
||||||
echo '<option value="'.$iZoomLevel.'"'.($bSel?'selected':'').'>'.$iZoomLevel.' '.$sLabel.'</option>'."\n";
|
echo '<option value="'.$iZoomLevel.'"'.($bSel?' selected="selected"':'').'>'.$iZoomLevel.' '.$sLabel.'</option>'."\n";
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</select>
|
</select>
|
||||||
@@ -65,7 +66,7 @@
|
|||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
|
||||||
<?php if ($aPlace) { ?>
|
<?php if (count($aPlace)>0) { ?>
|
||||||
|
|
||||||
<div id="searchresults" class="sidebar">
|
<div id="searchresults" class="sidebar">
|
||||||
<?php
|
<?php
|
||||||
@@ -96,7 +97,10 @@
|
|||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
<div id="map-wrapper">
|
<div id="map-wrapper">
|
||||||
<div id="map-position"></div>
|
<div id="map-position">
|
||||||
|
<div id="map-position-inner"></div>
|
||||||
|
<div id="map-position-close"><a href="#">hide</a></div>
|
||||||
|
</div>
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -111,13 +115,13 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$aNominatimMapInit = [
|
$aNominatimMapInit = array(
|
||||||
'zoom' => isset($_GET['zoom']) ? htmlspecialchars($_GET['zoom']) : CONST_Default_Zoom,
|
'zoom' => $iZoom !== false ? $iZoom : CONST_Default_Zoom,
|
||||||
'lat' => isset($_GET['lat'] ) ? htmlspecialchars($_GET['lat'] ) : CONST_Default_Lat,
|
'lat' => $fLat !== false ? $fLat : CONST_Default_Lat,
|
||||||
'lon' => isset($_GET['lon'] ) ? htmlspecialchars($_GET['lon'] ) : CONST_Default_Lon,
|
'lon' => $fLon !== false ? $fLon : CONST_Default_Lon,
|
||||||
'tile_url' => $sTileURL,
|
'tile_url' => $sTileURL,
|
||||||
'tile_attribution' => $sTileAttribution
|
'tile_attribution' => $sTileAttribution
|
||||||
];
|
);
|
||||||
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit, JSON_PRETTY_PRINT) . ';';
|
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit, JSON_PRETTY_PRINT) . ';';
|
||||||
|
|
||||||
echo 'var nominatim_results = ' . json_encode([$aPlace], JSON_PRETTY_PRINT) . ';';
|
echo 'var nominatim_results = ' . json_encode([$aPlace], JSON_PRETTY_PRINT) . ';';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
$aFilteredPlaces = array();
|
$aFilteredPlaces = array();
|
||||||
|
|
||||||
if (!sizeof($aPlace))
|
if (!sizeof($aPlace))
|
||||||
@@ -12,7 +13,7 @@
|
|||||||
{
|
{
|
||||||
if (isset($aPlace['place_id'])) $aFilteredPlaces['place_id'] = $aPlace['place_id'];
|
if (isset($aPlace['place_id'])) $aFilteredPlaces['place_id'] = $aPlace['place_id'];
|
||||||
$aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
|
$aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
|
||||||
$sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':'')));
|
$sOSMType = formatOSMType($aPlace['osm_type']);
|
||||||
if ($sOSMType)
|
if ($sOSMType)
|
||||||
{
|
{
|
||||||
$aFilteredPlaces['osm_type'] = $sOSMType;
|
$aFilteredPlaces['osm_type'] = $sOSMType;
|
||||||
@@ -24,6 +25,31 @@
|
|||||||
if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
|
if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
|
||||||
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
|
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
|
||||||
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
|
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
|
||||||
|
|
||||||
|
if (isset($aPlace['aBoundingBox']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['asgeojson']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['geojson'] = json_decode($aPlace['asgeojson']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['assvg']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['svg'] = $aPlace['assvg'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['astext']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['geotext'] = $aPlace['astext'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['askml']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['geokml'] = $aPlace['askml'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
javascript_renderData($aFilteredPlaces);
|
javascript_renderData($aFilteredPlaces);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
$aFilteredPlaces = array();
|
$aFilteredPlaces = array();
|
||||||
|
|
||||||
if (!sizeof($aPlace))
|
if (!sizeof($aPlace))
|
||||||
@@ -12,7 +13,7 @@
|
|||||||
{
|
{
|
||||||
if ($aPlace['place_id']) $aFilteredPlaces['place_id'] = $aPlace['place_id'];
|
if ($aPlace['place_id']) $aFilteredPlaces['place_id'] = $aPlace['place_id'];
|
||||||
$aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
|
$aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
|
||||||
$sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':'')));
|
$sOSMType = formatOSMType($aPlace['osm_type']);
|
||||||
if ($sOSMType)
|
if ($sOSMType)
|
||||||
{
|
{
|
||||||
$aFilteredPlaces['osm_type'] = $sOSMType;
|
$aFilteredPlaces['osm_type'] = $sOSMType;
|
||||||
@@ -36,6 +37,32 @@
|
|||||||
if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
|
if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
|
||||||
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
|
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
|
||||||
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
|
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
|
||||||
|
|
||||||
|
if (isset($aPlace['aBoundingBox']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['asgeojson']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['geojson'] = json_decode($aPlace['asgeojson']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['assvg']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['svg'] = $aPlace['assvg'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['astext']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['geotext'] = $aPlace['astext'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['askml']))
|
||||||
|
{
|
||||||
|
$aFilteredPlaces['geokml'] = $aPlace['askml'];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
javascript_renderData($aFilteredPlaces);
|
javascript_renderData($aFilteredPlaces);
|
||||||
|
|||||||
@@ -22,11 +22,38 @@
|
|||||||
{
|
{
|
||||||
echo "<result";
|
echo "<result";
|
||||||
if ($aPlace['place_id']) echo ' place_id="'.$aPlace['place_id'].'"';
|
if ($aPlace['place_id']) echo ' place_id="'.$aPlace['place_id'].'"';
|
||||||
$sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':'')));
|
$sOSMType = formatOSMType($aPlace['osm_type']);
|
||||||
if ($sOSMType) echo ' osm_type="'.$sOSMType.'"'.' osm_id="'.$aPlace['osm_id'].'"';
|
if ($sOSMType) echo ' osm_type="'.$sOSMType.'"'.' osm_id="'.$aPlace['osm_id'].'"';
|
||||||
if ($aPlace['ref']) echo ' ref="'.htmlspecialchars($aPlace['ref']).'"';
|
if ($aPlace['ref']) echo ' ref="'.htmlspecialchars($aPlace['ref']).'"';
|
||||||
if (isset($aPlace['lat'])) echo ' lat="'.htmlspecialchars($aPlace['lat']).'"';
|
if (isset($aPlace['lat'])) echo ' lat="'.htmlspecialchars($aPlace['lat']).'"';
|
||||||
if (isset($aPlace['lon'])) echo ' lon="'.htmlspecialchars($aPlace['lon']).'"';
|
if (isset($aPlace['lon'])) echo ' lon="'.htmlspecialchars($aPlace['lon']).'"';
|
||||||
|
if (isset($aPlace['aBoundingBox']))
|
||||||
|
{
|
||||||
|
echo ' boundingbox="';
|
||||||
|
echo join(',', $aPlace['aBoundingBox']);
|
||||||
|
echo '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['asgeojson']))
|
||||||
|
{
|
||||||
|
echo ' geojson=\'';
|
||||||
|
echo $aPlace['asgeojson'];
|
||||||
|
echo '\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['assvg']))
|
||||||
|
{
|
||||||
|
echo ' geosvg=\'';
|
||||||
|
echo $aPlace['assvg'];
|
||||||
|
echo '\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['astext']))
|
||||||
|
{
|
||||||
|
echo ' geotext=\'';
|
||||||
|
echo $aPlace['astext'];
|
||||||
|
echo '\'';
|
||||||
|
}
|
||||||
echo ">".htmlspecialchars($aPlace['langaddress'])."</result>";
|
echo ">".htmlspecialchars($aPlace['langaddress'])."</result>";
|
||||||
|
|
||||||
if (isset($aPlace['aAddress']))
|
if (isset($aPlace['aAddress']))
|
||||||
@@ -63,6 +90,14 @@
|
|||||||
}
|
}
|
||||||
echo "</namedetails>";
|
echo "</namedetails>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($aPlace['askml']))
|
||||||
|
{
|
||||||
|
echo "\n<geokml>";
|
||||||
|
echo $aPlace['askml'];
|
||||||
|
echo "</geokml>";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "</reversegeocode>";
|
echo "</reversegeocode>";
|
||||||
|
|||||||
@@ -9,27 +9,18 @@
|
|||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
function osm_link($aFeature)
|
function osmMapUrl($aFeature)
|
||||||
{
|
{
|
||||||
$sOSMType = ($aFeature['osm_type'] == 'N'?'node':($aFeature['osm_type'] == 'W'?'way':($aFeature['osm_type'] == 'R'?'relation':'')));
|
if (isset($sFeature['error_x']) && isset($sFeature['error_y']))
|
||||||
if ($sOSMType) {
|
|
||||||
return '<a href="http://www.openstreetmap.org/browse/'.$sOSMType.'/'.$aFeature['osm_id'].'">'.$sOSMType.' '.$aFeature['osm_id'].'</a>';
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function osm_map_url($aFeature)
|
|
||||||
{
|
{
|
||||||
$sLon = $aFeature['error_x'];
|
$sBaseUrl = '//www.openstreetmap.org/';
|
||||||
$sLat = $aFeature['error_y'];
|
$sOSMType = formatOSMType($aFeature['osm_type'], false);
|
||||||
|
|
||||||
if (isset($sLat))
|
|
||||||
{
|
|
||||||
$sOSMType = ($aFeature['osm_type'] == 'N'?'node':($aFeature['osm_type'] == 'W'?'way':($aFeature['osm_type'] == 'R'?'relation':'')));
|
|
||||||
if ($sOSMType)
|
if ($sOSMType)
|
||||||
{
|
{
|
||||||
return "http://www.openstreetmap.org/?lat=".$sLat."&lon=".$sLon."&zoom=18&layers=M&".$sOSMType."=".$aFeature['osm_id'];
|
$sBaseUrl += $sOSMType.'/'.$aFeature['osm_id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return '<a href="'.$sBaseUrl.'?mlat='.$aFeature['error_y'].'&mlon='.$aFeature['error_x'].'">view on osm.org</a>';
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -45,7 +36,7 @@
|
|||||||
return "http://localhost:8111/load_and_zoom?left=".($sLon-$fWidth)."&right=".($sLon+$fWidth)."&top=".($sLat+$fWidth)."&bottom=".($sLat-$fWidth);
|
return "http://localhost:8111/load_and_zoom?left=".($sLon-$fWidth)."&right=".($sLon+$fWidth)."&top=".($sLat+$fWidth)."&bottom=".($sLat-$fWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sOSMType = ($aFeature['osm_type'] == 'N'?'node':($aFeature['osm_type'] == 'W'?'way':($aFeature['osm_type'] == 'R'?'relation':'')));
|
$sOSMType = formatOSMType($aFeature['osm_type'], false);
|
||||||
if ($sOSMType)
|
if ($sOSMType)
|
||||||
{
|
{
|
||||||
return 'http://localhost:8111/import?url=http://www.openstreetmap.org/api/0.6/'.$sOSMType.'/'.$aFeature['osm_id'].'/full';
|
return 'http://localhost:8111/import?url=http://www.openstreetmap.org/api/0.6/'.$sOSMType.'/'.$aFeature['osm_id'].'/full';
|
||||||
@@ -63,7 +54,7 @@
|
|||||||
|
|
||||||
if (isset($sLat))
|
if (isset($sLat))
|
||||||
{
|
{
|
||||||
return "http://www.openstreetmap.org/edit?editor=potlatch2&bbox=".($sLon-$fWidth).",".($sLat-$fWidth).",".($sLon+$fWidth).",".($sLat+$fWidth);
|
return "//www.openstreetmap.org/edit?editor=potlatch2&bbox=".($sLon-$fWidth).",".($sLat-$fWidth).",".($sLon+$fWidth).",".($sLat+$fWidth);
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -87,7 +78,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
OSM: <span class="label"><?php echo osm_link($aPointDetails); ?><span>
|
OSM: <span class="label"><?php echo osmLink($aPointDetails); ?><span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@@ -95,9 +86,7 @@
|
|||||||
<p>
|
<p>
|
||||||
<?php echo $aPointDetails['errormessage']?$aPointDetails['errormessage']:'unknown'; ?>
|
<?php echo $aPointDetails['errormessage']?$aPointDetails['errormessage']:'unknown'; ?>
|
||||||
</p>
|
</p>
|
||||||
<?php if (osm_map_url($aPointDetails)) { ?>
|
<?php echo osmMapUrl($aPointDetails); ?>
|
||||||
<a href="<?php echo osm_map_url($aPointDetails); ?>">view on osm.org</a>
|
|
||||||
<?php } ?>
|
|
||||||
|
|
||||||
<h4>Edit</h4>
|
<h4>Edit</h4>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
function headline($sTitle)
|
function headline($sTitle)
|
||||||
@@ -20,30 +19,6 @@
|
|||||||
echo "<tr class='all-columns'><td colspan='6'><h3>".$sTitle."</h3></td></tr>\n";
|
echo "<tr class='all-columns'><td colspan='6'><h3>".$sTitle."</h3></td></tr>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
function osm_link($aFeature)
|
|
||||||
{
|
|
||||||
$sOSMType = ($aFeature['osm_type'] == 'N'?'node':($aFeature['osm_type'] == 'W'?'way':($aFeature['osm_type'] == 'R'?'relation':'')));
|
|
||||||
if ($sOSMType)
|
|
||||||
{
|
|
||||||
return '<a href="http://www.openstreetmap.org/browse/'.$sOSMType.'/'.$aFeature['osm_id'].'">'.$sOSMType.' '.$aFeature['osm_id'].'</a>';
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function wikipedia_link($aFeature)
|
|
||||||
{
|
|
||||||
if ($aFeature['wikipedia'])
|
|
||||||
{
|
|
||||||
list($sWikipediaLanguage,$sWikipediaArticle) = explode(':',$aFeature['wikipedia']);
|
|
||||||
return '<a href="https://'.$sWikipediaLanguage.'.wikipedia.org/wiki/'.urlencode($sWikipediaArticle).'" target="_blank">'.$aFeature['wikipedia'].'</a>';
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function nominatim_link($aFeature, $sTitle)
|
|
||||||
{
|
|
||||||
return '<a href="details.php?place_id='.$aFeature['place_id'].'">'.$sTitle.'</a>';
|
|
||||||
}
|
|
||||||
|
|
||||||
function format_distance($fDistance)
|
function format_distance($fDistance)
|
||||||
{
|
{
|
||||||
@@ -78,18 +53,6 @@
|
|||||||
return $sHTML;
|
return $sHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
// function hash_to_subtable($aAssociatedList)
|
|
||||||
// {
|
|
||||||
// $sHTML = '<table class="table">';
|
|
||||||
// foreach($aAssociatedList as $sKey => $sValue)
|
|
||||||
// {
|
|
||||||
// $sHTML = $sHTML . '<tr><td>'.$sKey.'</td><td class="name">'.$sValue.'</td></tr>'."\n";
|
|
||||||
// }
|
|
||||||
// $sHTML = $sHTML . '</table>';
|
|
||||||
// return $sHTML;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
function map_icon($sIcon)
|
function map_icon($sIcon)
|
||||||
{
|
{
|
||||||
if ($sIcon){
|
if ($sIcon){
|
||||||
@@ -104,15 +67,26 @@
|
|||||||
echo '<tr class="' . ($bNotUsed?'notused':'') . '">'."\n";
|
echo '<tr class="' . ($bNotUsed?'notused':'') . '">'."\n";
|
||||||
echo ' <td class="name">'.(trim($aAddressLine['localname'])?$aAddressLine['localname']:'<span class="noname">No Name</span>')."</td>\n";
|
echo ' <td class="name">'.(trim($aAddressLine['localname'])?$aAddressLine['localname']:'<span class="noname">No Name</span>')."</td>\n";
|
||||||
echo ' <td>' . $aAddressLine['class'].':'.$aAddressLine['type'] . "</td>\n";
|
echo ' <td>' . $aAddressLine['class'].':'.$aAddressLine['type'] . "</td>\n";
|
||||||
echo ' <td>' . osm_link($aAddressLine) . "</td>\n";
|
echo ' <td>' . osmLink($aAddressLine) . "</td>\n";
|
||||||
echo ' <td>' . (isset($aAddressLine['admin_level']) ? $aAddressLine['admin_level'] : '') . "</td>\n";
|
echo ' <td>' . (isset($aAddressLine['admin_level']) ? $aAddressLine['admin_level'] : '') . "</td>\n";
|
||||||
// echo '<td>' . (isset($aAddressLine['rank_search_label']) ? $aAddressLine['rank_search_label'] : '') ."</td>\n";
|
|
||||||
// echo ', <span class="area">'.($aAddressLine['fromarea']=='t'?'Polygon':'Point').'</span>';
|
|
||||||
echo ' <td>' . format_distance($aAddressLine['distance'])."</td>\n";
|
echo ' <td>' . format_distance($aAddressLine['distance'])."</td>\n";
|
||||||
echo ' <td>' . nominatim_link($aAddressLine,'details >') . "</td>\n";
|
echo ' <td>' . detailsLink($aAddressLine,'details >') . "</td>\n";
|
||||||
echo "</tr>\n";
|
echo "</tr>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _one_keyword_row($keyword_token,$word_id){
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo '<td>';
|
||||||
|
// mark partial tokens (those starting with a space) with a star for readability
|
||||||
|
echo ($keyword_token[0]==' '?'*':'');
|
||||||
|
echo $keyword_token;
|
||||||
|
if (isset($word_id))
|
||||||
|
{
|
||||||
|
echo '</td><td>word id: '.$word_id;
|
||||||
|
}
|
||||||
|
echo "</td></tr>\n";
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
||||||
@@ -144,10 +118,10 @@
|
|||||||
}
|
}
|
||||||
kv('Coverage' , ($aPointDetails['isarea']=='t'?'Polygon':'Point') );
|
kv('Coverage' , ($aPointDetails['isarea']=='t'?'Polygon':'Point') );
|
||||||
kv('Centre Point' , $aPointDetails['lat'].','.$aPointDetails['lon'] );
|
kv('Centre Point' , $aPointDetails['lat'].','.$aPointDetails['lon'] );
|
||||||
kv('OSM' , osm_link($aPointDetails) );
|
kv('OSM' , osmLink($aPointDetails) );
|
||||||
if ($aPointDetails['wikipedia'])
|
if ($aPointDetails['wikipedia'])
|
||||||
{
|
{
|
||||||
kv('Wikipedia Calculated' , wikipedia_link($aPointDetails) );
|
kv('Wikipedia Calculated' , wikipediaLink($aPointDetails) );
|
||||||
}
|
}
|
||||||
|
|
||||||
kv('Extra Tags' , hash_to_subtable($aPointDetails['aExtraTags']) );
|
kv('Extra Tags' , hash_to_subtable($aPointDetails['aExtraTags']) );
|
||||||
@@ -174,7 +148,6 @@
|
|||||||
<td>Type</td>
|
<td>Type</td>
|
||||||
<td>OSM</td>
|
<td>OSM</td>
|
||||||
<td>Admin level</td>
|
<td>Admin level</td>
|
||||||
<!-- <td>Search rank</td> -->
|
|
||||||
<td>Distance</td>
|
<td>Distance</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -209,7 +182,7 @@
|
|||||||
headline('Name Keywords');
|
headline('Name Keywords');
|
||||||
foreach($aPlaceSearchNameKeywords as $aRow)
|
foreach($aPlaceSearchNameKeywords as $aRow)
|
||||||
{
|
{
|
||||||
echo '<div>'.$aRow['word_token']."</div>\n";
|
_one_keyword_row($aRow['word_token'], $aRow['word_id']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +191,7 @@
|
|||||||
headline('Address Keywords');
|
headline('Address Keywords');
|
||||||
foreach($aPlaceSearchAddressKeywords as $aRow)
|
foreach($aPlaceSearchAddressKeywords as $aRow)
|
||||||
{
|
{
|
||||||
echo '<div>'.($aRow['word_token'][0]==' '?'*':'').$aRow['word_token'].'('.$aRow['word_id'].')'."</div>\n";
|
_one_keyword_row($aRow['word_token'], $aRow['word_id']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,9 +224,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// headline('Other Parts');
|
|
||||||
// headline('Linked To');
|
|
||||||
|
|
||||||
echo "</table>\n";
|
echo "</table>\n";
|
||||||
?>
|
?>
|
||||||
|
|
||||||
@@ -264,17 +234,17 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$aNominatimMapInit = [
|
$aNominatimMapInit = array(
|
||||||
'tile_url' => $sTileURL,
|
'tile_url' => $sTileURL,
|
||||||
'tile_attribution' => $sTileAttribution
|
'tile_attribution' => $sTileAttribution
|
||||||
];
|
);
|
||||||
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit, JSON_PRETTY_PRINT) . ';';
|
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit, JSON_PRETTY_PRINT) . ';';
|
||||||
|
|
||||||
$aPlace = [
|
$aPlace = array(
|
||||||
'outlinestring' => $aPointDetails['outlinestring'],
|
'asgeojson' => $aPointDetails['asgeojson'],
|
||||||
'lon' => $aPointDetails['lon'],
|
'lon' => $aPointDetails['lon'],
|
||||||
'lat' => $aPointDetails['lat'],
|
'lat' => $aPointDetails['lat'],
|
||||||
];
|
);
|
||||||
echo 'var nominatim_result = ' . json_encode($aPlace, JSON_PRETTY_PRINT) . ';';
|
echo 'var nominatim_result = ' . json_encode($aPlace, JSON_PRETTY_PRINT) . ';';
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,5 +10,4 @@
|
|||||||
<script src="js/jquery.min.js"></script>
|
<script src="js/jquery.min.js"></script>
|
||||||
<script src="js/bootstrap.min.js"></script>
|
<script src="js/bootstrap.min.js"></script>
|
||||||
<script src="js/leaflet.min.js"></script>
|
<script src="js/leaflet.min.js"></script>
|
||||||
<script src="js/leaflet-omnivore.min.js"></script>
|
|
||||||
<script src="js/nominatim-ui.js"></script>
|
<script src="js/nominatim-ui.js"></script>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>OpenStreetMap Nominatim: Search</title>
|
<title>OpenStreetMap Nominatim: Search</title>
|
||||||
|
<meta content="IE=edge" http-equiv="x-ua-compatible" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<base href="<?php echo CONST_Website_BaseURL;?>" />
|
<base href="<?php echo CONST_Website_BaseURL;?>" />
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="last-updated" class="col-xs-4 text-center">
|
<div id="last-updated" class="col-xs-4 text-center">
|
||||||
<?php if ($sDataDate){ ?>
|
<?php if (isset($sDataDate)){ ?>
|
||||||
Data last updated:
|
Data last updated:
|
||||||
<br>
|
<br>
|
||||||
<?php echo $sDataDate; ?>
|
<?php echo $sDataDate; ?>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
to check how the address was generated before reporting a problem.
|
to check how the address was generated before reporting a problem.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Use <a target="_blank" href="https://github.com/twain47/nominatim/issues">Nominatim issues on github</a>
|
Use <a target="_blank" href="https://github.com/openstreetmap/nominatim/issues">Nominatim issues on github</a>
|
||||||
to report problems.
|
to report problems.
|
||||||
<!-- You can search for existing bug reports
|
<!-- You can search for existing bug reports
|
||||||
<a href="http://trac.openstreetmap.org/query?status=new&status=assigned&status=reopened&component=nominatim&order=priority">here</a>.</p>
|
<a href="http://trac.openstreetmap.org/query?status=new&status=assigned&status=reopened&component=nominatim&order=priority">here</a>.</p>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
'place_id'=>$aPointDetails['place_id'],
|
'place_id'=>$aPointDetails['place_id'],
|
||||||
);
|
);
|
||||||
|
|
||||||
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':'')));
|
$sOSMType = formatOSMType($aPointDetails['osm_type']);
|
||||||
if ($sOSMType)
|
if ($sOSMType)
|
||||||
{
|
{
|
||||||
$aPlace['osm_type'] = $sOSMType;
|
$aPlace['osm_type'] = $sOSMType;
|
||||||
|
|||||||
@@ -17,19 +17,16 @@
|
|||||||
<div class="form-group search-button-group">
|
<div class="form-group search-button-group">
|
||||||
<button type="submit" class="btn btn-primary btn-sm">Search</button>
|
<button type="submit" class="btn btn-primary btn-sm">Search</button>
|
||||||
<?php if (CONST_Search_AreaPolygons) { ?>
|
<?php if (CONST_Search_AreaPolygons) { ?>
|
||||||
<!-- <input type="checkbox" value="1" name="polygon" <?php if ($bAsText) echo "checked='checked'"; ?>/> Highlight -->
|
<input type="hidden" value="1" name="polygon_geojson" />
|
||||||
<input type="hidden" value="1" name="polygon" />
|
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<input type="hidden" name="viewbox" value="<?php echo $sViewBox; ?>" />
|
<input type="hidden" name="viewbox" value="<?php if (isset($aMoreParams['viewbox'])) echo ($aMoreParams['viewbox']); ?>" />
|
||||||
<div class="checkbox-inline">
|
<div class="checkbox-inline">
|
||||||
<label>
|
<input type="checkbox" id="use_viewbox" <?php if (isset($aMoreParams['viewbox'])) echo "checked='checked'"; ?>>
|
||||||
<input type="checkbox" id="use_viewbox" <?php if ($sViewBox) echo "checked='checked'"; ?>>
|
<label for="use_viewbox">apply viewbox</label>
|
||||||
apply viewbox
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-type-link">
|
<div class="search-type-link">
|
||||||
<a href="<?php echo CONST_Website_BaseURL; ?>reverse.php?format=html">reverse search</a>
|
<a id="switch-to-reverse" href="<?php echo CONST_Website_BaseURL; ?>reverse.php?format=html">reverse search</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@@ -81,7 +78,10 @@
|
|||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
<div id="map-wrapper">
|
<div id="map-wrapper">
|
||||||
<div id="map-position"></div>
|
<div id="map-position">
|
||||||
|
<div id="map-position-inner"></div>
|
||||||
|
<div id="map-position-close"><a href="#">hide</a></div>
|
||||||
|
</div>
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -96,13 +96,13 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$aNominatimMapInit = [
|
$aNominatimMapInit = array(
|
||||||
'zoom' => $iZoom,
|
'zoom' => CONST_Default_Zoom,
|
||||||
'lat' => $fLat,
|
'lat' => CONST_Default_Lat,
|
||||||
'lon' => $fLon,
|
'lon' => CONST_Default_Lon,
|
||||||
'tile_url' => $sTileURL,
|
'tile_url' => CONST_Map_Tile_URL,
|
||||||
'tile_attribution' => $sTileAttribution
|
'tile_attribution' => CONST_Map_Tile_Attribution
|
||||||
];
|
);
|
||||||
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit, JSON_PRETTY_PRINT) . ';';
|
echo 'var nominatim_map_init = ' . json_encode($aNominatimMapInit, JSON_PRETTY_PRINT) . ';';
|
||||||
|
|
||||||
echo 'var nominatim_results = ' . json_encode($aSearchResults, JSON_PRETTY_PRINT) . ';';
|
echo 'var nominatim_results = ' . json_encode($aSearchResults, JSON_PRETTY_PRINT) . ';';
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
|
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
|
||||||
);
|
);
|
||||||
|
|
||||||
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':'')));
|
$sOSMType = formatOSMType($aPointDetails['osm_type']);
|
||||||
if ($sOSMType)
|
if ($sOSMType)
|
||||||
{
|
{
|
||||||
$aPlace['osm_type'] = $sOSMType;
|
$aPlace['osm_type'] = $sOSMType;
|
||||||
@@ -18,13 +18,9 @@
|
|||||||
|
|
||||||
if (isset($aPointDetails['aBoundingBox']))
|
if (isset($aPointDetails['aBoundingBox']))
|
||||||
{
|
{
|
||||||
$aPlace['boundingbox'] = array(
|
$aPlace['boundingbox'] = $aPointDetails['aBoundingBox'];
|
||||||
$aPointDetails['aBoundingBox'][0],
|
|
||||||
$aPointDetails['aBoundingBox'][1],
|
|
||||||
$aPointDetails['aBoundingBox'][2],
|
|
||||||
$aPointDetails['aBoundingBox'][3]);
|
|
||||||
|
|
||||||
if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons)
|
if (isset($aPointDetails['aPolyPoints']))
|
||||||
{
|
{
|
||||||
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
|
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
$aFilteredPlaces = array();
|
$aFilteredPlaces = array();
|
||||||
foreach($aSearchResults as $iResNum => $aPointDetails)
|
foreach($aSearchResults as $iResNum => $aPointDetails)
|
||||||
{
|
{
|
||||||
@@ -7,7 +8,7 @@
|
|||||||
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
|
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
|
||||||
);
|
);
|
||||||
|
|
||||||
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':'')));
|
$sOSMType = formatOSMType($aPointDetails['osm_type']);
|
||||||
if ($sOSMType)
|
if ($sOSMType)
|
||||||
{
|
{
|
||||||
$aPlace['osm_type'] = $sOSMType;
|
$aPlace['osm_type'] = $sOSMType;
|
||||||
@@ -16,13 +17,9 @@
|
|||||||
|
|
||||||
if (isset($aPointDetails['aBoundingBox']))
|
if (isset($aPointDetails['aBoundingBox']))
|
||||||
{
|
{
|
||||||
$aPlace['boundingbox'] = array(
|
$aPlace['boundingbox'] = $aPointDetails['aBoundingBox'];
|
||||||
$aPointDetails['aBoundingBox'][0],
|
|
||||||
$aPointDetails['aBoundingBox'][1],
|
|
||||||
$aPointDetails['aBoundingBox'][2],
|
|
||||||
$aPointDetails['aBoundingBox'][3]);
|
|
||||||
|
|
||||||
if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons)
|
if (isset($aPointDetails['aPolyPoints']))
|
||||||
{
|
{
|
||||||
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
|
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,22 +10,19 @@
|
|||||||
echo " timestamp='".date(DATE_RFC822)."'";
|
echo " timestamp='".date(DATE_RFC822)."'";
|
||||||
echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'";
|
echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'";
|
||||||
echo " querystring='".htmlspecialchars($sQuery, ENT_QUOTES)."'";
|
echo " querystring='".htmlspecialchars($sQuery, ENT_QUOTES)."'";
|
||||||
if ($sViewBox) echo " viewbox='".htmlspecialchars($sViewBox, ENT_QUOTES)."'";
|
if (isset($aMoreParams['viewbox'])) echo " viewbox='".htmlspecialchars($aMoreParams['viewbox'], ENT_QUOTES)."'";
|
||||||
echo " polygon='".($bShowPolygons?'true':'false')."'";
|
echo " polygon='".(isset($aMoreParams['polygon'])?'true':'false')."'";
|
||||||
if (sizeof($aExcludePlaceIDs))
|
if (isset($aMoreParams['exclude_place_ids']))
|
||||||
{
|
{
|
||||||
echo " exclude_place_ids='".htmlspecialchars(join(',',$aExcludePlaceIDs))."'";
|
echo " exclude_place_ids='".htmlspecialchars($aMoreParams['exclude_place_ids'])."'";
|
||||||
}
|
}
|
||||||
if ($sMoreURL)
|
|
||||||
{
|
|
||||||
echo " more_url='".htmlspecialchars($sMoreURL)."'";
|
echo " more_url='".htmlspecialchars($sMoreURL)."'";
|
||||||
}
|
|
||||||
echo ">\n";
|
echo ">\n";
|
||||||
|
|
||||||
foreach($aSearchResults as $iResNum => $aResult)
|
foreach($aSearchResults as $iResNum => $aResult)
|
||||||
{
|
{
|
||||||
echo "<place place_id='".$aResult['place_id']."'";
|
echo "<place place_id='".$aResult['place_id']."'";
|
||||||
$sOSMType = ($aResult['osm_type'] == 'N'?'node':($aResult['osm_type'] == 'W'?'way':($aResult['osm_type'] == 'R'?'relation':'')));
|
$sOSMType = formatOSMType($aResult['osm_type']);
|
||||||
if ($sOSMType)
|
if ($sOSMType)
|
||||||
{
|
{
|
||||||
echo " osm_type='$sOSMType'";
|
echo " osm_type='$sOSMType'";
|
||||||
@@ -36,13 +33,10 @@
|
|||||||
if (isset($aResult['aBoundingBox']))
|
if (isset($aResult['aBoundingBox']))
|
||||||
{
|
{
|
||||||
echo ' boundingbox="';
|
echo ' boundingbox="';
|
||||||
echo $aResult['aBoundingBox'][0];
|
echo join(',',$aResult['aBoundingBox']);
|
||||||
echo ','.$aResult['aBoundingBox'][1];
|
|
||||||
echo ','.$aResult['aBoundingBox'][2];
|
|
||||||
echo ','.$aResult['aBoundingBox'][3];
|
|
||||||
echo '"';
|
echo '"';
|
||||||
|
|
||||||
if ($bShowPolygons && isset($aResult['aPolyPoints']))
|
if (isset($aResult['aPolyPoints']))
|
||||||
{
|
{
|
||||||
echo ' polygonpoints=\'';
|
echo ' polygonpoints=\'';
|
||||||
echo json_encode($aResult['aPolyPoints']);
|
echo json_encode($aResult['aPolyPoints']);
|
||||||
|
|||||||
@@ -1,125 +0,0 @@
|
|||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_LIB_POSTGRESQL_SVR([MINIMUM-VERSION])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# This macro provides tests of availability of PostgreSQL server library
|
|
||||||
#
|
|
||||||
# This macro calls:
|
|
||||||
#
|
|
||||||
# AC_SUBST(POSTGRESQL_PGXS)
|
|
||||||
# AC_SUBST(POSTGRESQL_SERVER_CFLAGS)
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Mateusz Loskot <mateusz@loskot.net>
|
|
||||||
# Copyright (c) 2015 Sarah Hoffmann <lonia@denofr.de>
|
|
||||||
#
|
|
||||||
# Copying and distribution of this file, with or without modification, are
|
|
||||||
# permitted in any medium without royalty provided the copyright notice
|
|
||||||
# and this notice are preserved.
|
|
||||||
|
|
||||||
AC_DEFUN([AX_LIB_POSTGRESQL_SVR],
|
|
||||||
[
|
|
||||||
AC_ARG_WITH([postgresql],
|
|
||||||
AC_HELP_STRING([--with-postgresql-svr=@<:@ARG@:>@],
|
|
||||||
[use PostgreSQL server library @<:@default=yes@:>@, optionally specify path to pg_config]
|
|
||||||
),
|
|
||||||
[
|
|
||||||
if test "$withval" = "no"; then
|
|
||||||
want_postgresql="no"
|
|
||||||
elif test "$withval" = "yes"; then
|
|
||||||
want_postgresql="yes"
|
|
||||||
else
|
|
||||||
want_postgresql="yes"
|
|
||||||
PG_CONFIG="$withval"
|
|
||||||
fi
|
|
||||||
],
|
|
||||||
[want_postgresql="yes"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dnl
|
|
||||||
dnl Check PostgreSQL server libraries
|
|
||||||
dnl
|
|
||||||
|
|
||||||
if test "$want_postgresql" = "yes"; then
|
|
||||||
|
|
||||||
if test -z "$PG_CONFIG" -o test; then
|
|
||||||
AC_PATH_PROG([PG_CONFIG], [pg_config], [])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test ! -x "$PG_CONFIG"; then
|
|
||||||
AC_MSG_ERROR([$PG_CONFIG does not exist or it is not an exectuable file])
|
|
||||||
PG_CONFIG="no"
|
|
||||||
found_postgresql="no"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$PG_CONFIG" != "no"; then
|
|
||||||
AC_MSG_CHECKING([for PostgreSQL server libraries])
|
|
||||||
|
|
||||||
POSTGRESQL_SERVER_CFLAGS="-I`$PG_CONFIG --includedir-server`"
|
|
||||||
|
|
||||||
POSTGRESQL_VERSION=`$PG_CONFIG --version | sed -e 's#PostgreSQL ##'`
|
|
||||||
|
|
||||||
POSTGRESQL_PGXS=`$PG_CONFIG --pgxs`
|
|
||||||
if test -f "$POSTGRESQL_PGXS"
|
|
||||||
then
|
|
||||||
found_postgresql="yes"
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
found_postgresql="no"
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl
|
|
||||||
dnl Check if required version of PostgreSQL is available
|
|
||||||
dnl
|
|
||||||
|
|
||||||
|
|
||||||
postgresql_version_req=ifelse([$1], [], [], [$1])
|
|
||||||
|
|
||||||
if test "$found_postgresql" = "yes" -a -n "$postgresql_version_req"; then
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([if PostgreSQL version is >= $postgresql_version_req])
|
|
||||||
|
|
||||||
dnl Decompose required version string of PostgreSQL
|
|
||||||
dnl and calculate its number representation
|
|
||||||
postgresql_version_req_major=`expr $postgresql_version_req : '\([[0-9]]*\)'`
|
|
||||||
postgresql_version_req_minor=`expr $postgresql_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
postgresql_version_req_micro=`expr $postgresql_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
if test "x$postgresql_version_req_micro" = "x"; then
|
|
||||||
postgresql_version_req_micro="0"
|
|
||||||
fi
|
|
||||||
|
|
||||||
postgresql_version_req_number=`expr $postgresql_version_req_major \* 1000000 \
|
|
||||||
\+ $postgresql_version_req_minor \* 1000 \
|
|
||||||
\+ $postgresql_version_req_micro`
|
|
||||||
|
|
||||||
dnl Decompose version string of installed PostgreSQL
|
|
||||||
dnl and calculate its number representation
|
|
||||||
postgresql_version_major=`expr $POSTGRESQL_VERSION : '\([[0-9]]*\)'`
|
|
||||||
postgresql_version_minor=`expr $POSTGRESQL_VERSION : '[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
postgresql_version_micro=`expr $POSTGRESQL_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
if test "x$postgresql_version_micro" = "x"; then
|
|
||||||
postgresql_version_micro="0"
|
|
||||||
fi
|
|
||||||
|
|
||||||
postgresql_version_number=`expr $postgresql_version_major \* 1000000 \
|
|
||||||
\+ $postgresql_version_minor \* 1000 \
|
|
||||||
\+ $postgresql_version_micro`
|
|
||||||
|
|
||||||
postgresql_version_check=`expr $postgresql_version_number \>\= $postgresql_version_req_number`
|
|
||||||
if test "$postgresql_version_check" = "1"; then
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST([POSTGRESQL_PGXS])
|
|
||||||
AC_SUBST([POSTGRESQL_SERVER_CFLAGS])
|
|
||||||
])
|
|
||||||
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_LIB_XML2([MINIMUM-VERSION])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# This macro provides tests of availability of xml2 'libxml2' library
|
|
||||||
# of particular version or newer.
|
|
||||||
#
|
|
||||||
# AX_LIB_LIBXML2 macro takes only one argument which is optional. If
|
|
||||||
# there is no required version passed, then macro does not run version
|
|
||||||
# test.
|
|
||||||
#
|
|
||||||
# The --with-libxml2 option takes one of three possible values:
|
|
||||||
#
|
|
||||||
# no - do not check for xml2 library
|
|
||||||
#
|
|
||||||
# yes - do check for xml2 library in standard locations (xml2-config
|
|
||||||
# should be in the PATH)
|
|
||||||
#
|
|
||||||
# path - complete path to xml2-config utility, use this option if xml2-config
|
|
||||||
# can't be found in the PATH
|
|
||||||
#
|
|
||||||
# This macro calls:
|
|
||||||
#
|
|
||||||
# AC_SUBST(XML2_CFLAGS)
|
|
||||||
# AC_SUBST(XML2_LDFLAGS)
|
|
||||||
# AC_SUBST(XML2_VERSION)
|
|
||||||
#
|
|
||||||
# And sets:
|
|
||||||
#
|
|
||||||
# HAVE_XML2
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2009 Hartmut Holzgraefe <hartmut@php.net>
|
|
||||||
#
|
|
||||||
# Copying and distribution of this file, with or without modification, are
|
|
||||||
# permitted in any medium without royalty provided the copyright notice
|
|
||||||
# and this notice are preserved.
|
|
||||||
|
|
||||||
AC_DEFUN([AX_LIB_XML2],
|
|
||||||
[
|
|
||||||
AC_ARG_WITH([libxml2],
|
|
||||||
AC_HELP_STRING([--with-libxml2=@<:@ARG@:>@],
|
|
||||||
[use libxml2 library @<:@default=yes@:>@, optionally specify path to xml2-config]
|
|
||||||
),
|
|
||||||
[
|
|
||||||
if test "$withval" = "no"; then
|
|
||||||
want_libxml2="no"
|
|
||||||
elif test "$withval" = "yes"; then
|
|
||||||
want_libxml2="yes"
|
|
||||||
else
|
|
||||||
want_libxml2="yes"
|
|
||||||
XML2_CONFIG="$withval"
|
|
||||||
fi
|
|
||||||
],
|
|
||||||
[want_libxml2="yes"]
|
|
||||||
)
|
|
||||||
|
|
||||||
XML2_CFLAGS=""
|
|
||||||
XML2_LDFLAGS=""
|
|
||||||
XML2_VERSION=""
|
|
||||||
|
|
||||||
dnl
|
|
||||||
dnl Check xml2 libraries (libxml2)
|
|
||||||
dnl
|
|
||||||
|
|
||||||
if test "$want_libxml2" = "yes"; then
|
|
||||||
|
|
||||||
if test -z "$XML2_CONFIG" -o test; then
|
|
||||||
AC_PATH_PROG([XML2_CONFIG], [xml2-config], [])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test ! -x "$XML2_CONFIG"; then
|
|
||||||
AC_MSG_ERROR([$XML2_CONFIG does not exist or it is not an exectuable file])
|
|
||||||
XML2_CONFIG="no"
|
|
||||||
found_libxml2="no"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$XML2_CONFIG" != "no"; then
|
|
||||||
AC_MSG_CHECKING([for xml2 libraries])
|
|
||||||
|
|
||||||
XML2_CFLAGS="`$XML2_CONFIG --cflags`"
|
|
||||||
XML2_LDFLAGS="`$XML2_CONFIG --libs`"
|
|
||||||
|
|
||||||
XML2_VERSION=`$XML2_CONFIG --version`
|
|
||||||
|
|
||||||
AC_DEFINE([HAVE_XML2], [1],
|
|
||||||
[Define to 1 if xml2 libraries are available])
|
|
||||||
|
|
||||||
found_libxml2="yes"
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
else
|
|
||||||
found_libxml2="no"
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl
|
|
||||||
dnl Check if required version of xml2 is available
|
|
||||||
dnl
|
|
||||||
|
|
||||||
|
|
||||||
libxml2_version_req=ifelse([$1], [], [], [$1])
|
|
||||||
|
|
||||||
|
|
||||||
if test "$found_libxml2" = "yes" -a -n "$libxml2_version_req"; then
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([if libxml2 version is >= $libxml2_version_req])
|
|
||||||
|
|
||||||
dnl Decompose required version string of libxml2
|
|
||||||
dnl and calculate its number representation
|
|
||||||
libxml2_version_req_major=`expr $libxml2_version_req : '\([[0-9]]*\)'`
|
|
||||||
libxml2_version_req_minor=`expr $libxml2_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
libxml2_version_req_micro=`expr $libxml2_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
if test "x$libxml2_version_req_micro" = "x"; then
|
|
||||||
libxml2_version_req_micro="0"
|
|
||||||
fi
|
|
||||||
|
|
||||||
libxml2_version_req_number=`expr $libxml2_version_req_major \* 1000000 \
|
|
||||||
\+ $libxml2_version_req_minor \* 1000 \
|
|
||||||
\+ $libxml2_version_req_micro`
|
|
||||||
|
|
||||||
dnl Decompose version string of installed PostgreSQL
|
|
||||||
dnl and calculate its number representation
|
|
||||||
libxml2_version_major=`expr $XML2_VERSION : '\([[0-9]]*\)'`
|
|
||||||
libxml2_version_minor=`expr $XML2_VERSION : '[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
libxml2_version_micro=`expr $XML2_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
if test "x$libxml2_version_micro" = "x"; then
|
|
||||||
libxml2_version_micro="0"
|
|
||||||
fi
|
|
||||||
|
|
||||||
libxml2_version_number=`expr $libxml2_version_major \* 1000000 \
|
|
||||||
\+ $libxml2_version_minor \* 1000 \
|
|
||||||
\+ $libxml2_version_micro`
|
|
||||||
|
|
||||||
libxml2_version_check=`expr $libxml2_version_number \>\= $libxml2_version_req_number`
|
|
||||||
if test "$libxml2_version_check" = "1"; then
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST([XML2_VERSION])
|
|
||||||
AC_SUBST([XML2_CFLAGS])
|
|
||||||
AC_SUBST([XML2_LDFLAGS])
|
|
||||||
])
|
|
||||||
|
|
||||||
10
module/CMakeLists.txt
Normal file
10
module/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# just use the pgxs makefile
|
||||||
|
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/dummy
|
||||||
|
COMMAND PGXS=${PGXS} PG_CONFIG=${PG_CONFIG} MODSRCDIR=${CMAKE_CURRENT_SOURCE_DIR} $(MAKE) -f ${CMAKE_CURRENT_SOURCE_DIR}/Makefile
|
||||||
|
COMMENT "Running external makefile ${PGXS}"
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_CUSTOM_TARGET( nominatim_lib ALL
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/dummy
|
||||||
|
)
|
||||||
|
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
MODULES = nominatim
|
MODULES = nominatim
|
||||||
PGXS := @POSTGRESQL_PGXS@
|
PG_CPPFLAGS = -I$(MODSRCDIR)
|
||||||
PG_CONFIG := @PG_CONFIG@
|
|
||||||
include $(PGXS)
|
include $(PGXS)
|
||||||
|
|
||||||
|
VPATH = $(MODSRCDIR)
|
||||||
|
|
||||||
all:
|
all:
|
||||||
chmod 755 nominatim.so
|
chmod 755 nominatim.so
|
||||||
|
|
||||||
File diff suppressed because one or more lines are too long
12
nominatim/CMakeLists.txt
Normal file
12
nominatim/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
add_executable(nominatim export.c geometry.cpp import.c index.c input.c nominatim.c postgresql.c sprompt.c)
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
CHECK_INCLUDE_FILE(byteswap.h HAVE_BYTESWAP_H)
|
||||||
|
CHECK_INCLUDE_FILE(sys/endian.h HAVE_SYS_ENDIAN_H)
|
||||||
|
if(HAVE_BYTESWAP_H)
|
||||||
|
target_compile_definitions(nominatim PRIVATE HAVE_BYTESWAP_H)
|
||||||
|
endif(HAVE_BYTESWAP_H)
|
||||||
|
if(HAVE_SYS_ENDIAN_H)
|
||||||
|
target_compile_definitions(nominatim PRIVATE HAVE_SYS_ENDIAN_H)
|
||||||
|
endif(HAVE_SYS_ENDIAN_H)
|
||||||
|
target_link_libraries(nominatim ${LIBXML2_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PostgreSQL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
bin_PROGRAMS = nominatim
|
|
||||||
|
|
||||||
nominatim_SOURCES = export.c geometry.cpp import.c index.c input.c nominatim.c postgresql.c sprompt.c
|
|
||||||
|
|
||||||
AM_CFLAGS = @PTHREAD_CFLAGS@ @POSTGRESQL_CPPFLAGS@ @XML_CPPFLAGS@ @BZIP2_CFLAGS@ @GEOS_CFLAGS@ @PROJ_CFLAGS@ -DVERSION='"@PACKAGE_VERSION@"'
|
|
||||||
AM_CPPFLAGS = @PTHREAD_CFLAGS@ @POSTGRESQL_CPPFLAGS@ @XML_CPPFLAGS@ @BZIP2_CFLAGS@ @GEOS_CFLAGS@ @PROJ_CFLAGS@
|
|
||||||
|
|
||||||
nominatim_LDADD = @PTHREAD_CFLAGS@ @POSTGRESQL_LDFLAGS@ @POSTGRESQL_LIBS@ @XML_LIBS@ @BZIP2_LDFLAGS@ @BZIP2_LIBS@ @GEOS_LDFLAGS@ @GEOS_LIBS@ @PROJ_LDFLAGS@ @PROJ_LIBS@ -lz
|
|
||||||
|
|
||||||
@@ -486,7 +486,7 @@ void EndElement(xmlTextReaderPtr reader, const xmlChar *name)
|
|||||||
}
|
}
|
||||||
paramValues[7] = (const char *)featureExtraTagString;
|
paramValues[7] = (const char *)featureExtraTagString;
|
||||||
|
|
||||||
if (strlen(feature.parentPlaceID) == 0)
|
if (xmlStrlen(feature.parentPlaceID) == 0)
|
||||||
paramValues[8] = "0";
|
paramValues[8] = "0";
|
||||||
else
|
else
|
||||||
paramValues[8] = (const char *)feature.parentPlaceID;
|
paramValues[8] = (const char *)feature.parentPlaceID;
|
||||||
@@ -541,10 +541,10 @@ void EndElement(xmlTextReaderPtr reader, const xmlChar *name)
|
|||||||
|
|
||||||
if (featureNameLines)
|
if (featureNameLines)
|
||||||
{
|
{
|
||||||
if (strlen(feature.parentPlaceID) > 0 && featureAddressLines == 0)
|
if (xmlStrlen(feature.parentPlaceID) > 0 && featureAddressLines == 0)
|
||||||
{
|
{
|
||||||
paramValues[0] = (const char *)place_id;
|
paramValues[0] = (const char *)place_id;
|
||||||
paramValues[1] = feature.parentPlaceID;
|
paramValues[1] = (const char *)feature.parentPlaceID;
|
||||||
if (verbose) fprintf(stderr, "search_name_from_parent_insert: INSERT %s %s\n", paramValues[0], paramValues[1]);
|
if (verbose) fprintf(stderr, "search_name_from_parent_insert: INSERT %s %s\n", paramValues[0], paramValues[1]);
|
||||||
res = PQexecPrepared(conn, "search_name_from_parent_insert", 2, paramValues, NULL, NULL, 0);
|
res = PQexecPrepared(conn, "search_name_from_parent_insert", 2, paramValues, NULL, NULL, 0);
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
* triggers indexing (reparenting etc.) through setting resetting indexed_status: update placex/osmline set indexed_status = 0 where indexed_status > 0
|
||||||
|
* triggers placex_update and osmline_update
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -19,24 +21,21 @@
|
|||||||
|
|
||||||
extern int verbose;
|
extern int verbose;
|
||||||
|
|
||||||
void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile)
|
void run_indexing(int rank, int interpolation, PGconn *conn, int num_threads,
|
||||||
|
struct index_thread_data * thread_data, const char *structuredoutputfile)
|
||||||
{
|
{
|
||||||
struct index_thread_data * thread_data;
|
|
||||||
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
int tuples, count, sleepcount;
|
int tuples, count, sleepcount;
|
||||||
|
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
time_t rankStartTime;
|
time_t rankStartTime;
|
||||||
int rankTotalTuples;
|
int rankTotalTuples;
|
||||||
int rankCountTuples;
|
int rankCountTuples;
|
||||||
float rankPerSecond;
|
float rankPerSecond;
|
||||||
|
|
||||||
PGconn *conn;
|
|
||||||
PGresult * res;
|
|
||||||
PGresult * resSectors;
|
PGresult * resSectors;
|
||||||
PGresult * resPlaces;
|
PGresult * resPlaces;
|
||||||
PGresult * resNULL;
|
PGresult * resNULL;
|
||||||
|
|
||||||
int rank;
|
|
||||||
int i;
|
int i;
|
||||||
int iSector;
|
int iSector;
|
||||||
int iResult;
|
int iResult;
|
||||||
@@ -51,93 +50,6 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
|
|||||||
xmlTextWriterPtr writer;
|
xmlTextWriterPtr writer;
|
||||||
pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
Oid pg_prepare_params[2];
|
|
||||||
|
|
||||||
conn = PQconnectdb(conninfo);
|
|
||||||
if (PQstatus(conn) != CONNECTION_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
pg_prepare_params[0] = PG_OID_INT4;
|
|
||||||
res = PQprepare(conn, "index_sectors",
|
|
||||||
"select geometry_sector,count(*) from placex where rank_search = $1 and indexed_status > 0 group by geometry_sector order by geometry_sector",
|
|
||||||
1, pg_prepare_params);
|
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
PQclear(res);
|
|
||||||
|
|
||||||
pg_prepare_params[0] = PG_OID_INT4;
|
|
||||||
res = PQprepare(conn, "index_nosectors",
|
|
||||||
"select 0::integer,count(*) from placex where rank_search = $1 and indexed_status > 0",
|
|
||||||
1, pg_prepare_params);
|
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
PQclear(res);
|
|
||||||
|
|
||||||
pg_prepare_params[0] = PG_OID_INT4;
|
|
||||||
pg_prepare_params[1] = PG_OID_INT4;
|
|
||||||
res = PQprepare(conn, "index_sector_places",
|
|
||||||
"select place_id from placex where rank_search = $1 and geometry_sector = $2 and indexed_status > 0",
|
|
||||||
2, pg_prepare_params);
|
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed preparing index_sector_places: %s\n", PQerrorMessage(conn));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
PQclear(res);
|
|
||||||
|
|
||||||
pg_prepare_params[0] = PG_OID_INT4;
|
|
||||||
res = PQprepare(conn, "index_nosector_places",
|
|
||||||
"select place_id from placex where rank_search = $1 and indexed_status > 0 order by geometry_sector",
|
|
||||||
1, pg_prepare_params);
|
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed preparing index_nosector_places: %s\n", PQerrorMessage(conn));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
PQclear(res);
|
|
||||||
|
|
||||||
// Build the data for each thread
|
|
||||||
thread_data = (struct index_thread_data *)malloc(sizeof(struct index_thread_data)*num_threads);
|
|
||||||
for (i = 0; i < num_threads; i++)
|
|
||||||
{
|
|
||||||
thread_data[i].conn = PQconnectdb(conninfo);
|
|
||||||
if (PQstatus(thread_data[i].conn) != CONNECTION_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(thread_data[i].conn));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
pg_prepare_params[0] = PG_OID_INT8;
|
|
||||||
res = PQprepare(thread_data[i].conn, "index_placex",
|
|
||||||
"update placex set indexed_status = 0 where place_id = $1",
|
|
||||||
1, pg_prepare_params);
|
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed preparing index_placex: %s\n", PQerrorMessage(conn));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
PQclear(res);
|
|
||||||
|
|
||||||
/*res = PQexec(thread_data[i].conn, "set enable_seqscan = false");
|
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed disabling sequential scan: %s\n", PQerrorMessage(conn));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
PQclear(res);*/
|
|
||||||
|
|
||||||
nominatim_exportCreatePreparedQueries(thread_data[i].conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the output file
|
// Create the output file
|
||||||
writer = NULL;
|
writer = NULL;
|
||||||
if (structuredoutputfile)
|
if (structuredoutputfile)
|
||||||
@@ -145,11 +57,15 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
|
|||||||
writer = nominatim_exportXMLStart(structuredoutputfile);
|
writer = nominatim_exportXMLStart(structuredoutputfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Starting indexing rank (%i to %i) using %i threads\n", rank_min, rank_max, num_threads);
|
if (interpolation)
|
||||||
|
{
|
||||||
for (rank = rank_min; rank <= rank_max; rank++)
|
fprintf(stderr, "Starting interpolation lines (location_property_osmline)\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Starting rank %d\n", rank);
|
fprintf(stderr, "Starting rank %d\n", rank);
|
||||||
|
}
|
||||||
|
|
||||||
rankCountTuples = 0;
|
rankCountTuples = 0;
|
||||||
rankPerSecond = 0;
|
rankPerSecond = 0;
|
||||||
|
|
||||||
@@ -157,11 +73,15 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
|
|||||||
paramValues[0] = (char *)¶mRank;
|
paramValues[0] = (char *)¶mRank;
|
||||||
paramLengths[0] = sizeof(paramRank);
|
paramLengths[0] = sizeof(paramRank);
|
||||||
paramFormats[0] = 1;
|
paramFormats[0] = 1;
|
||||||
// if (rank < 16)
|
|
||||||
// resSectors = PQexecPrepared(conn, "index_nosectors", 1, paramValues, paramLengths, paramFormats, 1);
|
|
||||||
// else
|
|
||||||
resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1);
|
|
||||||
|
|
||||||
|
if (interpolation)
|
||||||
|
{
|
||||||
|
resSectors = PQexecPrepared(conn, "index_sectors_osmline", 0, NULL, 0, NULL, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1);
|
||||||
|
}
|
||||||
if (PQresultStatus(resSectors) != PGRES_TUPLES_OK)
|
if (PQresultStatus(resSectors) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn));
|
fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn));
|
||||||
@@ -220,21 +140,42 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
|
|||||||
|
|
||||||
// Get all the place_id's for this sector
|
// Get all the place_id's for this sector
|
||||||
paramRank = PGint32(rank);
|
paramRank = PGint32(rank);
|
||||||
paramValues[0] = (char *)¶mRank;
|
|
||||||
paramLengths[0] = sizeof(paramRank);
|
|
||||||
paramFormats[0] = 1;
|
|
||||||
paramSector = PGint32(sector);
|
paramSector = PGint32(sector);
|
||||||
paramValues[1] = (char *)¶mSector;
|
|
||||||
paramLengths[1] = sizeof(paramSector);
|
|
||||||
paramFormats[1] = 1;
|
|
||||||
if (rankTotalTuples-rankCountTuples < num_threads*1000)
|
if (rankTotalTuples-rankCountTuples < num_threads*1000)
|
||||||
{
|
{
|
||||||
iResult = PQsendQueryPrepared(conn, "index_nosector_places", 1, paramValues, paramLengths, paramFormats, 1);
|
// no sectors
|
||||||
|
if (interpolation)
|
||||||
|
{
|
||||||
|
iResult = PQsendQueryPrepared(conn, "index_nosector_places_osmline", 0, NULL, 0, NULL, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
paramValues[0] = (char *)¶mRank;
|
||||||
|
paramLengths[0] = sizeof(paramRank);
|
||||||
|
paramFormats[0] = 1;
|
||||||
|
iResult = PQsendQueryPrepared(conn, "index_nosector_places", 1, paramValues, paramLengths, paramFormats, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (interpolation)
|
||||||
|
{
|
||||||
|
iResult = PQsendQueryPrepared(conn, "index_sector_places_osmline", 1, paramValues, paramLengths, paramFormats, 1);
|
||||||
|
paramValues[0] = (char *)¶mSector;
|
||||||
|
paramLengths[0] = sizeof(paramSector);
|
||||||
|
paramFormats[0] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paramValues[0] = (char *)¶mRank;
|
||||||
|
paramLengths[0] = sizeof(paramRank);
|
||||||
|
paramFormats[0] = 1;
|
||||||
|
paramValues[1] = (char *)¶mSector;
|
||||||
|
paramLengths[1] = sizeof(paramSector);
|
||||||
|
paramFormats[1] = 1;
|
||||||
iResult = PQsendQueryPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1);
|
iResult = PQsendQueryPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!iResult)
|
if (!iResult)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
|
fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
|
||||||
@@ -242,7 +183,6 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iSector > 0)
|
if (iSector > 0)
|
||||||
{
|
{
|
||||||
count = 0;
|
count = 0;
|
||||||
@@ -260,6 +200,14 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
|
|||||||
thread_data[i].count_mutex = &count_mutex;
|
thread_data[i].count_mutex = &count_mutex;
|
||||||
thread_data[i].writer = writer;
|
thread_data[i].writer = writer;
|
||||||
thread_data[i].writer_mutex = &writer_mutex;
|
thread_data[i].writer_mutex = &writer_mutex;
|
||||||
|
if (interpolation)
|
||||||
|
{
|
||||||
|
thread_data[i].table = 0; // use interpolations table
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread_data[i].table = 1; // use placex table
|
||||||
|
}
|
||||||
pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]);
|
pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +221,15 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
|
|||||||
if (sleepcount++ > 500)
|
if (sleepcount++ > 500)
|
||||||
{
|
{
|
||||||
rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1);
|
rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1);
|
||||||
|
if(interpolation)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " Done %i in %i @ %f per second - Interpolation lines ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
fprintf(stderr, " Done %i in %i @ %f per second - Rank %i ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, rank, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
|
fprintf(stderr, " Done %i in %i @ %f per second - Rank %i ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, rank, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
|
||||||
|
}
|
||||||
|
|
||||||
sleepcount = 0;
|
sleepcount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,11 +260,163 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
|
|||||||
PQclear(resSectors);
|
PQclear(resSectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writer)
|
void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile)
|
||||||
{
|
{
|
||||||
nominatim_exportXMLEnd(writer);
|
struct index_thread_data * thread_data;
|
||||||
|
|
||||||
|
PGconn *conn;
|
||||||
|
PGresult * res;
|
||||||
|
|
||||||
|
int rank;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
xmlTextWriterPtr writer;
|
||||||
|
pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
Oid pg_prepare_params[2];
|
||||||
|
|
||||||
|
conn = PQconnectdb(conninfo);
|
||||||
|
if (PQstatus(conn) != CONNECTION_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pg_prepare_params[0] = PG_OID_INT4;
|
||||||
|
res = PQprepare(conn, "index_sectors",
|
||||||
|
"select geometry_sector,count(*) from placex where rank_search = $1 and indexed_status > 0 group by geometry_sector order by geometry_sector",
|
||||||
|
1, pg_prepare_params);
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
res = PQprepare(conn, "index_sectors_osmline",
|
||||||
|
"select geometry_sector,count(*) from location_property_osmline where indexed_status > 0 group by geometry_sector order by geometry_sector",
|
||||||
|
0, NULL);
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
pg_prepare_params[0] = PG_OID_INT4;
|
||||||
|
res = PQprepare(conn, "index_nosectors",
|
||||||
|
"select 0::integer,count(*) from placex where rank_search = $1 and indexed_status > 0",
|
||||||
|
1, pg_prepare_params);
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
pg_prepare_params[0] = PG_OID_INT4;
|
||||||
|
pg_prepare_params[1] = PG_OID_INT4;
|
||||||
|
res = PQprepare(conn, "index_sector_places",
|
||||||
|
"select place_id from placex where rank_search = $1 and geometry_sector = $2 and indexed_status > 0",
|
||||||
|
2, pg_prepare_params);
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed preparing index_sector_places: %s\n", PQerrorMessage(conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
pg_prepare_params[0] = PG_OID_INT4;
|
||||||
|
res = PQprepare(conn, "index_nosector_places",
|
||||||
|
"select place_id from placex where rank_search = $1 and indexed_status > 0 order by geometry_sector",
|
||||||
|
1, pg_prepare_params);
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed preparing index_nosector_places: %s\n", PQerrorMessage(conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
pg_prepare_params[0] = PG_OID_INT4;
|
||||||
|
res = PQprepare(conn, "index_sector_places_osmline",
|
||||||
|
"select place_id from location_property_osmline where geometry_sector = $1 and indexed_status > 0",
|
||||||
|
1, pg_prepare_params);
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed preparing index_sector_places: %s\n", PQerrorMessage(conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
res = PQprepare(conn, "index_nosector_places_osmline",
|
||||||
|
"select place_id from location_property_osmline where indexed_status > 0 order by geometry_sector",
|
||||||
|
0, NULL);
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed preparing index_nosector_places: %s\n", PQerrorMessage(conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
// Build the data for each thread
|
||||||
|
thread_data = (struct index_thread_data *)malloc(sizeof(struct index_thread_data)*num_threads);
|
||||||
|
for (i = 0; i < num_threads; i++)
|
||||||
|
{
|
||||||
|
thread_data[i].conn = PQconnectdb(conninfo);
|
||||||
|
if (PQstatus(thread_data[i].conn) != CONNECTION_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(thread_data[i].conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
pg_prepare_params[0] = PG_OID_INT8;
|
||||||
|
res = PQprepare(thread_data[i].conn, "index_placex",
|
||||||
|
"update placex set indexed_status = 0 where place_id = $1",
|
||||||
|
1, pg_prepare_params);
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed preparing index_placex: %s\n", PQerrorMessage(thread_data[i].conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
pg_prepare_params[0] = PG_OID_INT8;
|
||||||
|
res = PQprepare(thread_data[i].conn, "index_osmline",
|
||||||
|
"update location_property_osmline set indexed_status = 0 where place_id = $1",
|
||||||
|
1, pg_prepare_params);
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed preparing index_osmline: %s\n", PQerrorMessage(thread_data[i].conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
// Make sure the error message is not localized as we parse it later.
|
||||||
|
res = PQexec(thread_data[i].conn, "SET lc_messages TO 'C'");
|
||||||
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to set langauge: %s\n", PQerrorMessage(thread_data[i].conn));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
nominatim_exportCreatePreparedQueries(thread_data[i].conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fprintf(stderr, "Starting indexing rank (%i to %i) using %i threads\n", rank_min, rank_max, num_threads);
|
||||||
|
|
||||||
|
for (rank = rank_min; rank <= rank_max; rank++)
|
||||||
|
{
|
||||||
|
// OSMLINE: do reindexing (=> reparenting) for interpolation lines at rank 30, but before all other objects of rank 30
|
||||||
|
// reason: houses (rank 30) depend on the updated interpolation line, when reparenting (see placex_update in functions.sql)
|
||||||
|
if (rank == 30)
|
||||||
|
{
|
||||||
|
run_indexing(rank, 1, conn, num_threads, thread_data, structuredoutputfile);
|
||||||
|
}
|
||||||
|
run_indexing(rank, 0, conn, num_threads, thread_data, structuredoutputfile);
|
||||||
|
}
|
||||||
// Close all connections
|
// Close all connections
|
||||||
for (i = 0; i < num_threads; i++)
|
for (i = 0; i < num_threads; i++)
|
||||||
{
|
{
|
||||||
@@ -330,6 +438,9 @@ void *nominatim_indexThread(void * thread_data_in)
|
|||||||
uint64_t paramPlaceID;
|
uint64_t paramPlaceID;
|
||||||
uint64_t place_id;
|
uint64_t place_id;
|
||||||
time_t updateStartTime;
|
time_t updateStartTime;
|
||||||
|
uint table;
|
||||||
|
|
||||||
|
table = (uint)(thread_data->table);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -361,20 +472,41 @@ void *nominatim_indexThread(void * thread_data_in)
|
|||||||
paramValues[0] = (char *)¶mPlaceID;
|
paramValues[0] = (char *)¶mPlaceID;
|
||||||
paramLengths[0] = sizeof(paramPlaceID);
|
paramLengths[0] = sizeof(paramPlaceID);
|
||||||
paramFormats[0] = 1;
|
paramFormats[0] = 1;
|
||||||
|
if (table == 1) // table=1 for placex
|
||||||
|
{
|
||||||
res = PQexecPrepared(thread_data->conn, "index_placex", 1, paramValues, paramLengths, paramFormats, 1);
|
res = PQexecPrepared(thread_data->conn, "index_placex", 1, paramValues, paramLengths, paramFormats, 1);
|
||||||
|
}
|
||||||
|
else // table=0 for osmline
|
||||||
|
{
|
||||||
|
res = PQexecPrepared(thread_data->conn, "index_osmline", 1, paramValues, paramLengths, paramFormats, 1);
|
||||||
|
}
|
||||||
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
||||||
done = 1;
|
done = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!strncmp(PQerrorMessage(thread_data->conn), "ERROR: deadlock detected", 25))
|
if (!strncmp(PQerrorMessage(thread_data->conn), "ERROR: deadlock detected", 25))
|
||||||
|
{
|
||||||
|
if (table == 1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "index_placex: UPDATE failed - deadlock, retrying (%ld)\n", place_id);
|
fprintf(stderr, "index_placex: UPDATE failed - deadlock, retrying (%ld)\n", place_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "index_osmline: UPDATE failed - deadlock, retrying (%ld)\n", place_id);
|
||||||
|
}
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
sleep(rand() % 10);
|
sleep(rand() % 10);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (table == 1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "index_placex: UPDATE failed: %s", PQerrorMessage(thread_data->conn));
|
fprintf(stderr, "index_placex: UPDATE failed: %s", PQerrorMessage(thread_data->conn));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "index_osmline: UPDATE failed: %s", PQerrorMessage(thread_data->conn));
|
||||||
|
}
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ struct index_thread_data
|
|||||||
pthread_mutex_t * count_mutex;
|
pthread_mutex_t * count_mutex;
|
||||||
xmlTextWriterPtr writer;
|
xmlTextWriterPtr writer;
|
||||||
pthread_mutex_t * writer_mutex;
|
pthread_mutex_t * writer_mutex;
|
||||||
|
uint table;
|
||||||
};
|
};
|
||||||
void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile);
|
void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile);
|
||||||
void *nominatim_indexThread(void * thread_data_in);
|
void *nominatim_indexThread(void * thread_data_in);
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
|
|
||||||
fprintf(stderr, "nominatim version %s\n\n", VERSION);
|
fprintf(stderr, "nominatim version %s\n\n", NOMINATIM_VERSION);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ struct output_options
|
|||||||
int expire_tiles_zoom_min; /* Minimum zoom level for tile expiry list */
|
int expire_tiles_zoom_min; /* Minimum zoom level for tile expiry list */
|
||||||
const char *expire_tiles_filename; /* File name to output expired tiles list to */
|
const char *expire_tiles_filename; /* File name to output expired tiles list to */
|
||||||
int enable_hstore; /* add an additional hstore column with objects key/value pairs */
|
int enable_hstore; /* add an additional hstore column with objects key/value pairs */
|
||||||
int enable_multi; /* Output multi-geometries intead of several simple geometries */
|
int enable_multi; /* Output multi-geometries instead of several simple geometries */
|
||||||
char** hstore_columns; /* list of columns that should be written into their own hstore column */
|
char** hstore_columns; /* list of columns that should be written into their own hstore column */
|
||||||
int n_hstore_columns; /* number of hstore columns */
|
int n_hstore_columns; /* number of hstore columns */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,11 @@
|
|||||||
#define PG_OID_INT8 20
|
#define PG_OID_INT8 20
|
||||||
#define PG_OID_INT4 23
|
#define PG_OID_INT4 23
|
||||||
|
|
||||||
|
#if defined(HAVE_BYTESWAP_H)
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
|
#elif defined(HAVE_SYS_ENDIAN_H)
|
||||||
|
#include <sys/endian.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
#define PGint16(x) (x)
|
#define PGint16(x) (x)
|
||||||
|
|||||||
Submodule osm2pgsql updated: 8179cdb67e...c27acf1705
152
phpcs.xml
Normal file
152
phpcs.xml
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="Nominatim Standard">
|
||||||
|
|
||||||
|
<description>Nominatim coding standard</description>
|
||||||
|
|
||||||
|
<!-- based on another standard, you can find it here -->
|
||||||
|
<!-- /usr/share/php/PHP/CodeSniffer/Standards/PSR2/ruleset.xml -->
|
||||||
|
<!-- https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/PSR2/ruleset.xml -->
|
||||||
|
<rule ref="PSR2"/>
|
||||||
|
|
||||||
|
<rule ref="Generic.Files.LineLength">
|
||||||
|
<properties>
|
||||||
|
<property name="lineLimit" value="199"/>
|
||||||
|
<property name="absoluteLineLimit" value="199"/>
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- "A file should declare new symbols (classes, functions, constants, etc.) and cause no
|
||||||
|
other side effects, or it should execute logic with side effects, but should not do both."
|
||||||
|
... we have too many script and includes to be able to enforce that.
|
||||||
|
-->
|
||||||
|
<rule ref="PSR1.Files.SideEffects.FoundWithSymbols">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- **************************************************************
|
||||||
|
DOCUMENTATION
|
||||||
|
************************************************************** -->
|
||||||
|
|
||||||
|
<rule ref="PEAR.Commenting.FunctionComment.Missing">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- **************************************************************
|
||||||
|
COMMENTS
|
||||||
|
************************************************************** -->
|
||||||
|
|
||||||
|
<!-- any comments in the lines before function() are better than forcing
|
||||||
|
a PHPdoc style right now -->
|
||||||
|
<rule ref="PEAR.Commenting.FunctionComment.WrongStyle">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- We allow comments after statements -->
|
||||||
|
<rule ref="Squiz.Commenting.PostStatementComment.Found">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
<!-- ... even without space e.g. //some words -->
|
||||||
|
<rule ref="Squiz.Commenting.InlineComment.NoSpaceBefore">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
<!-- blank lines after inline comments are fine -->
|
||||||
|
<rule ref="Squiz.Commenting.InlineComment.SpacingAfter">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- Comments don't have to start uppercase -->
|
||||||
|
<rule ref="Squiz.Commenting.InlineComment.NotCapital">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
<!-- Comments don't have to end with one of .!? -->
|
||||||
|
<rule ref="Squiz.Commenting.InlineComment.InvalidEndChar">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
<!-- Empty comments are fine -->
|
||||||
|
<rule ref="Squiz.Commenting.InlineComment.Empty">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- **************************************************************
|
||||||
|
INDENTATION, SPACING
|
||||||
|
************************************************************** -->
|
||||||
|
|
||||||
|
<!-- We don't need 2 blank lines after function -->
|
||||||
|
<rule ref="Squiz.WhiteSpace.FunctionSpacing.After">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- Aligned looks nicer, but causes too many warnings currently -->
|
||||||
|
<rule ref="Generic.Formatting.MultipleStatementAlignment.NotSame">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
<rule ref="Generic.Formatting.MultipleStatementAlignment.NotSameWarning">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- Aligned looks nicer, but causes too many warnings currently -->
|
||||||
|
<rule ref="Squiz.Arrays.ArrayDeclaration.DoubleArrowNotAligned">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- **************************************************************
|
||||||
|
VARIABLES
|
||||||
|
************************************************************** -->
|
||||||
|
|
||||||
|
<!-- CONST_this_var is fine, we don't need ConstThisVar -->
|
||||||
|
<rule ref="Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- simply disagree with "Each line in an array declaration must end in a comma" -->
|
||||||
|
<rule ref="Squiz.Arrays.ArrayDeclaration.NoCommaAfterLast">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
<rule ref="Squiz.Arrays.ArrayDeclaration.NoComma">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- We allow "$abc = array($aPoint[1], $aPoint[2])" -->
|
||||||
|
<rule ref="Squiz.Arrays.ArrayDeclaration.SingleLineNotAllowed">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- **************************************************************
|
||||||
|
CONTROL STRUCTURES
|
||||||
|
************************************************************** -->
|
||||||
|
|
||||||
|
<!-- we allow "if (a) echo 'b'" without brackets -->
|
||||||
|
<rule ref="Generic.ControlStructures.InlineControlStructure.NotAllowed">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- We allow "if (a)". No need for "if (a === TRUE)" -->
|
||||||
|
<rule ref="Squiz.Operators.ComparisonOperatorUsage.ImplicitTrue">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
<!-- ... same for "if (!a)" -->
|
||||||
|
<rule ref="Squiz.Operators.ComparisonOperatorUsage.NotAllowed">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ruleset>
|
||||||
@@ -8,13 +8,13 @@
|
|||||||
processIsolation="false"
|
processIsolation="false"
|
||||||
stopOnFailure="false"
|
stopOnFailure="false"
|
||||||
syntaxCheck="true"
|
syntaxCheck="true"
|
||||||
bootstrap="tests-php/bootstrap.php"
|
bootstrap="test/php/bootstrap.php"
|
||||||
>
|
>
|
||||||
<php>
|
<php>
|
||||||
</php>
|
</php>
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite name="Nominatim PHP Test Suite">
|
<testsuite name="Nominatim PHP Test Suite">
|
||||||
<directory>./tests-php/Nominatim</directory>
|
<directory>./test/php/Nominatim</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
<filter>
|
<filter>
|
||||||
|
|||||||
123
settings/defaults.php
Normal file
123
settings/defaults.php
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
@define('CONST_BasePath', '@CMAKE_SOURCE_DIR@');
|
||||||
|
@define('CONST_InstallPath', '@CMAKE_BINARY_DIR@');
|
||||||
|
if (file_exists(getenv('NOMINATIM_SETTINGS'))) require_once(getenv('NOMINATIM_SETTINGS'));
|
||||||
|
if (file_exists(CONST_InstallPath.'/settings/local.php')) require_once(CONST_InstallPath.'/settings/local.php');
|
||||||
|
if (isset($_GET['debug']) && $_GET['debug']) @define('CONST_Debug', true);
|
||||||
|
|
||||||
|
// General settings
|
||||||
|
@define('CONST_Debug', false);
|
||||||
|
@define('CONST_Database_DSN', 'pgsql://@/nominatim'); // <driver>://<username>:<password>@<host>:<port>/<database>
|
||||||
|
@define('CONST_Database_Web_User', 'www-data');
|
||||||
|
@define('CONST_Max_Word_Frequency', '50000');
|
||||||
|
@define('CONST_Limit_Reindexing', true);
|
||||||
|
// Restrict search languages.
|
||||||
|
// Normally Nominatim will include all language variants of name:XX
|
||||||
|
// in the search index. Set this to a comma separated list of language
|
||||||
|
// codes, to restrict import to a subset of languages.
|
||||||
|
// Currently only affects the import of country names and special phrases.
|
||||||
|
@define('CONST_Languages', false);
|
||||||
|
// Rules for normalizing terms for comparison before doing comparisons.
|
||||||
|
// The default is to remove accents and punctuation and to lower-case the
|
||||||
|
// term. Spaces are kept but collapsed to one standard space.
|
||||||
|
@define('CONST_Term_Normalization_Rules', ":: NFD (); [:Nonspacing Mark:] >; :: lower (); [[:Punctuation:][:Space:]]+ > ' '; :: NFC ();");
|
||||||
|
|
||||||
|
// Set to false to avoid importing extra postcodes for the US.
|
||||||
|
@define('CONST_Use_Extra_US_Postcodes', true);
|
||||||
|
/* Set to true after importing Tiger house number data for the US.
|
||||||
|
Note: The tables must already exist or queries will throw errors.
|
||||||
|
After changing this setting run ./utils/setup --create-functions
|
||||||
|
again. */
|
||||||
|
@define('CONST_Use_US_Tiger_Data', false);
|
||||||
|
/* Set to true after importing other external house number data.
|
||||||
|
Note: the aux tables must already exist or queries will throw errors.
|
||||||
|
After changing this setting run ./utils/setup --create-functions
|
||||||
|
again. */
|
||||||
|
@define('CONST_Use_Aux_Location_data', false);
|
||||||
|
|
||||||
|
// Proxy settings
|
||||||
|
@define('CONST_HTTP_Proxy', false);
|
||||||
|
@define('CONST_HTTP_Proxy_Host', 'proxy.mydomain.com');
|
||||||
|
@define('CONST_HTTP_Proxy_Port', '3128');
|
||||||
|
@define('CONST_HTTP_Proxy_Login', '');
|
||||||
|
@define('CONST_HTTP_Proxy_Password', '');
|
||||||
|
|
||||||
|
// Paths
|
||||||
|
@define('CONST_ExtraDataPath', CONST_BasePath.'/data');
|
||||||
|
@define('CONST_Osm2pgsql_Binary', CONST_InstallPath.'/osm2pgsql/osm2pgsql');
|
||||||
|
@define('CONST_Pyosmium_Binary', '@PYOSMIUM_PATH@');
|
||||||
|
@define('CONST_Tiger_Data_Path', CONST_ExtraDataPath.'/tiger');
|
||||||
|
@define('CONST_Wikipedia_Data_Path', CONST_ExtraDataPath);
|
||||||
|
|
||||||
|
// osm2pgsql settings
|
||||||
|
@define('CONST_Osm2pgsql_Flatnode_File', null);
|
||||||
|
|
||||||
|
// tablespace settings
|
||||||
|
// osm2pgsql caching tables (aka slim mode tables) - update only
|
||||||
|
@define('CONST_Tablespace_Osm2pgsql_Data', false);
|
||||||
|
@define('CONST_Tablespace_Osm2pgsql_Index', false);
|
||||||
|
// osm2pgsql output tables (aka main table) - update only
|
||||||
|
@define('CONST_Tablespace_Place_Data', false);
|
||||||
|
@define('CONST_Tablespace_Place_Index', false);
|
||||||
|
// address computation tables - update only
|
||||||
|
@define('CONST_Tablespace_Address_Data', false);
|
||||||
|
@define('CONST_Tablespace_Address_Index', false);
|
||||||
|
// search tables - needed for lookups
|
||||||
|
@define('CONST_Tablespace_Search_Data', false);
|
||||||
|
@define('CONST_Tablespace_Search_Index', false);
|
||||||
|
// additional data, e.g. TIGER data, type searches - needed for lookups
|
||||||
|
@define('CONST_Tablespace_Aux_Data', false);
|
||||||
|
@define('CONST_Tablespace_Aux_Index', false);
|
||||||
|
|
||||||
|
//// Replication settings
|
||||||
|
|
||||||
|
// Base URL of replication service
|
||||||
|
@define('CONST_Replication_Url', 'http://planet.openstreetmap.org/replication/minute');
|
||||||
|
|
||||||
|
// Maximum size in MB of data to download per batch
|
||||||
|
@define('CONST_Replication_Max_Diff_size', '30');
|
||||||
|
// How long until the service publishes the next diff
|
||||||
|
// (relative to the age of data in the diff).
|
||||||
|
@define('CONST_Replication_Update_Interval', '75');
|
||||||
|
// How long to sleep when no update could be found
|
||||||
|
@define('CONST_Replication_Recheck_Interval', '60');
|
||||||
|
|
||||||
|
// Website settings
|
||||||
|
@define('CONST_NoAccessControl', true);
|
||||||
|
|
||||||
|
@define('CONST_Website_BaseURL', 'http://'.php_uname('n').'/');
|
||||||
|
// Language to assume when none is supplied with the query.
|
||||||
|
// When set to false, the local language (i.e. the name tag without suffix)
|
||||||
|
// will be used.
|
||||||
|
@define('CONST_Default_Language', false);
|
||||||
|
// Appearance of the map in the debug interface.
|
||||||
|
@define('CONST_Default_Lat', 20.0);
|
||||||
|
@define('CONST_Default_Lon', 0.0);
|
||||||
|
@define('CONST_Default_Zoom', 2);
|
||||||
|
@define('CONST_Map_Tile_URL', 'http://{s}.tile.osm.org/{z}/{x}/{y}.png');
|
||||||
|
@define('CONST_Map_Tile_Attribution', ''); // Set if tile source isn't osm.org
|
||||||
|
|
||||||
|
@define('CONST_Search_AreaPolygons', true);
|
||||||
|
|
||||||
|
@define('CONST_Search_BatchMode', false);
|
||||||
|
|
||||||
|
@define('CONST_Search_TryDroppedAddressTerms', false);
|
||||||
|
@define('CONST_Search_NameOnlySearchFrequencyThreshold', 500);
|
||||||
|
// If set to true, then reverse order of queries will be tried by default.
|
||||||
|
// When set to false only selected languages alloow reverse search.
|
||||||
|
@define('CONST_Search_ReversePlanForAll', true);
|
||||||
|
|
||||||
|
// Maximum number of OSM ids that may be queried at once
|
||||||
|
// for the places endpoint.
|
||||||
|
@define('CONST_Places_Max_ID_count', 50);
|
||||||
|
|
||||||
|
// Number of different geometry formats that may be queried in parallel.
|
||||||
|
// Set to zero to disable polygon output.
|
||||||
|
@define('CONST_PolygonOutput_MaximumTypes', 1);
|
||||||
|
|
||||||
|
// Log settings
|
||||||
|
// Set to true to log into new_query_log table.
|
||||||
|
// You should set up a cron job that regularly clears out this table.
|
||||||
|
@define('CONST_Log_DB', false);
|
||||||
|
// Set to a file name to enable logging to a file.
|
||||||
|
@define('CONST_Log_File', false);
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
amenity airport
|
|
||||||
amenity arts_centre
|
|
||||||
amenity atm
|
|
||||||
amenity auditorium
|
|
||||||
amenity bank
|
|
||||||
amenity bar
|
|
||||||
amenity bench
|
|
||||||
amenity bicycle_parking
|
|
||||||
amenity bicycle_rental
|
|
||||||
amenity brothel
|
|
||||||
amenity bureau_de_change
|
|
||||||
amenity bus_station
|
|
||||||
amenity cafe
|
|
||||||
amenity car_rental
|
|
||||||
amenity car_wash
|
|
||||||
amenity casino
|
|
||||||
amenity cinema
|
|
||||||
amenity clinic
|
|
||||||
amenity club
|
|
||||||
amenity college
|
|
||||||
amenity community_centre
|
|
||||||
amenity courthouse
|
|
||||||
amenity crematorium
|
|
||||||
amenity dentist
|
|
||||||
amenity doctors
|
|
||||||
amenity dormitory
|
|
||||||
amenity drinking_water
|
|
||||||
amenity driving_school
|
|
||||||
amenity embassy
|
|
||||||
amenity emergency_phone
|
|
||||||
amenity fast_food
|
|
||||||
amenity ferry_terminal
|
|
||||||
amenity fire_hydrant
|
|
||||||
amenity fire_station
|
|
||||||
amenity fountain
|
|
||||||
amenity fuel
|
|
||||||
amenity grave_yard
|
|
||||||
amenity hall
|
|
||||||
amenity health_centre
|
|
||||||
amenity hospital
|
|
||||||
amenity hotel
|
|
||||||
amenity hunting_stand
|
|
||||||
amenity ice_cream
|
|
||||||
amenity kindergarten
|
|
||||||
amenity library
|
|
||||||
amenity market
|
|
||||||
amenity marketplace
|
|
||||||
amenity nightclub
|
|
||||||
amenity nursery
|
|
||||||
amenity nursing_home
|
|
||||||
amenity office
|
|
||||||
amenity park
|
|
||||||
amenity parking
|
|
||||||
amenity pharmacy
|
|
||||||
amenity place_of_worship
|
|
||||||
amenity police
|
|
||||||
amenity post_box
|
|
||||||
amenity post_office
|
|
||||||
amenity preschool
|
|
||||||
amenity prison
|
|
||||||
amenity pub
|
|
||||||
amenity public_building
|
|
||||||
amenity public_market
|
|
||||||
amenity reception_area
|
|
||||||
amenity restaurant
|
|
||||||
amenity retirement_home
|
|
||||||
amenity sauna
|
|
||||||
amenity school
|
|
||||||
amenity shelter
|
|
||||||
amenity shop
|
|
||||||
amenity shopping
|
|
||||||
amenity social_club
|
|
||||||
amenity studio
|
|
||||||
amenity supermarket
|
|
||||||
amenity taxi
|
|
||||||
amenity telephone
|
|
||||||
amenity theatre
|
|
||||||
amenity toilets
|
|
||||||
amenity townhall
|
|
||||||
amenity university
|
|
||||||
amenity veterinary
|
|
||||||
amenity waste_basket
|
|
||||||
amenity wifi
|
|
||||||
amenity youth_centre
|
|
||||||
boundary administrative
|
|
||||||
building apartments
|
|
||||||
building block
|
|
||||||
building bunker
|
|
||||||
building chapel
|
|
||||||
building church
|
|
||||||
building commercial
|
|
||||||
building dormitory
|
|
||||||
building entrance
|
|
||||||
building faculty
|
|
||||||
building farm
|
|
||||||
building flats
|
|
||||||
building garage
|
|
||||||
building hospital
|
|
||||||
building hotel
|
|
||||||
building house
|
|
||||||
building industrial
|
|
||||||
building office
|
|
||||||
building public
|
|
||||||
building residential
|
|
||||||
building retail
|
|
||||||
building school
|
|
||||||
building shop
|
|
||||||
building stadium
|
|
||||||
building store
|
|
||||||
building terrace
|
|
||||||
building tower
|
|
||||||
building train_station
|
|
||||||
building university
|
|
||||||
highway bridleway
|
|
||||||
highway bus_stop
|
|
||||||
highway construction
|
|
||||||
highway cycleway
|
|
||||||
highway distance_marker
|
|
||||||
highway emergency_access_point
|
|
||||||
highway footway
|
|
||||||
highway gate
|
|
||||||
highway motorway_junction
|
|
||||||
highway path
|
|
||||||
highway pedestrian
|
|
||||||
highway platform
|
|
||||||
highway primary
|
|
||||||
highway primary_link
|
|
||||||
highway raceway
|
|
||||||
highway road
|
|
||||||
highway secondary
|
|
||||||
highway secondary_link
|
|
||||||
highway services
|
|
||||||
highway steps
|
|
||||||
highway tertiary
|
|
||||||
highway track
|
|
||||||
highway trail
|
|
||||||
highway trunk
|
|
||||||
highway trunk_link
|
|
||||||
highway unsurfaced
|
|
||||||
historic archaeological_site
|
|
||||||
historic battlefield
|
|
||||||
historic building
|
|
||||||
historic castle
|
|
||||||
historic church
|
|
||||||
historic house
|
|
||||||
historic icon
|
|
||||||
historic manor
|
|
||||||
historic memorial
|
|
||||||
historic mine
|
|
||||||
historic monument
|
|
||||||
historic museum
|
|
||||||
historic ruins
|
|
||||||
historic tower
|
|
||||||
historic wayside_cross
|
|
||||||
historic wayside_shrine
|
|
||||||
historic wreck
|
|
||||||
landuse cemetery
|
|
||||||
landuse commercial
|
|
||||||
landuse construction
|
|
||||||
landuse farm
|
|
||||||
landuse farmland
|
|
||||||
landuse farmyard
|
|
||||||
landuse forest
|
|
||||||
landuse grass
|
|
||||||
landuse industrial
|
|
||||||
@@ -1,51 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
# These settings control the import of special phrases from the wiki.
|
|
||||||
|
|
||||||
# Languages to download the special phrases for.
|
// These settings control the import of special phrases from the wiki.
|
||||||
$aLanguageIn = array(
|
|
||||||
'af',
|
|
||||||
'ar',
|
|
||||||
'br',
|
|
||||||
'ca',
|
|
||||||
'cs',
|
|
||||||
'de',
|
|
||||||
'en',
|
|
||||||
'es',
|
|
||||||
'et',
|
|
||||||
'eu',
|
|
||||||
'fa',
|
|
||||||
'fi',
|
|
||||||
'fr',
|
|
||||||
'gl',
|
|
||||||
'hr',
|
|
||||||
'hu',
|
|
||||||
'ia',
|
|
||||||
'is',
|
|
||||||
'it',
|
|
||||||
'ja',
|
|
||||||
'mk',
|
|
||||||
'nl',
|
|
||||||
'no',
|
|
||||||
'pl',
|
|
||||||
'ps',
|
|
||||||
'pt',
|
|
||||||
'ru',
|
|
||||||
'sk',
|
|
||||||
'sv',
|
|
||||||
'uk',
|
|
||||||
'vi',
|
|
||||||
);
|
|
||||||
|
|
||||||
# class/type combinations to exclude
|
// class/type combinations to exclude
|
||||||
$aTagsBlacklist = array(
|
$aTagsBlacklist
|
||||||
|
= array(
|
||||||
'boundary' => array('administrative'),
|
'boundary' => array('administrative'),
|
||||||
'place' => array('house', 'houses'),
|
'place' => array('house', 'houses'),
|
||||||
);
|
);
|
||||||
# If a class is in the white list then all types will
|
|
||||||
# be ignored except the ones given in the list.
|
// If a class is in the white list then all types will
|
||||||
# Also use this list to exclude an entire class from
|
// be ignored except the ones given in the list.
|
||||||
# special phrases.
|
// Also use this list to exclude an entire class from
|
||||||
$aTagsWhitelist = array(
|
// special phrases.
|
||||||
|
$aTagsWhitelist
|
||||||
|
= array(
|
||||||
'highway' => array('bus_stop', 'rest_area', 'raceway'),
|
'highway' => array('bus_stop', 'rest_area', 'raceway'),
|
||||||
'building' => array(),
|
'building' => array(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,120 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
if (file_exists(CONST_BasePath.'/settings/local.php')) require_once(CONST_BasePath.'/settings/local.php');
|
|
||||||
if (isset($_GET['debug']) && $_GET['debug']) @define('CONST_Debug', true);
|
|
||||||
|
|
||||||
// General settings
|
|
||||||
@define('CONST_Debug', false);
|
|
||||||
@define('CONST_Database_DSN', 'pgsql://@/nominatim'); // <driver>://<username>:<password>@<host>:<port>/<database>
|
|
||||||
@define('CONST_Database_Web_User', 'www-data');
|
|
||||||
@define('CONST_Max_Word_Frequency', '50000');
|
|
||||||
@define('CONST_Limit_Reindexing', true);
|
|
||||||
|
|
||||||
// Proxy settings
|
|
||||||
@define('CONST_HTTP_Proxy', false);
|
|
||||||
@define('CONST_HTTP_Proxy_Host', 'proxy.mydomain.com');
|
|
||||||
@define('CONST_HTTP_Proxy_Port', '3128');
|
|
||||||
@define('CONST_HTTP_Proxy_Login', '');
|
|
||||||
@define('CONST_HTTP_Proxy_Password', '');
|
|
||||||
|
|
||||||
// Software versions
|
|
||||||
@define('CONST_Postgresql_Version', '9.3'); // values: 9.0, ... , 9.4
|
|
||||||
@define('CONST_Postgis_Version', '2.1'); // values: 1.5, 2.0, 2.1
|
|
||||||
|
|
||||||
// Paths
|
|
||||||
@define('CONST_Path_Postgresql_Contrib', '/usr/share/postgresql/'.CONST_Postgresql_Version.'/contrib');
|
|
||||||
@define('CONST_Path_Postgresql_Postgis', CONST_Path_Postgresql_Contrib.'/postgis-'.CONST_Postgis_Version);
|
|
||||||
@define('CONST_Osm2pgsql_Binary', CONST_BasePath.'/osm2pgsql/osm2pgsql');
|
|
||||||
@define('CONST_Osmosis_Binary', '/usr/bin/osmosis');
|
|
||||||
@define('CONST_Tiger_Data_Path', CONST_BasePath.'/data/tiger');
|
|
||||||
|
|
||||||
// osm2pgsql settings
|
|
||||||
@define('CONST_Osm2pgsql_Flatnode_File', null);
|
|
||||||
|
|
||||||
// tablespace settings
|
|
||||||
// osm2pgsql caching tables (aka slim mode tables) - update only
|
|
||||||
@define('CONST_Tablespace_Osm2pgsql_Data', false);
|
|
||||||
@define('CONST_Tablespace_Osm2pgsql_Index', false);
|
|
||||||
// osm2pgsql output tables (aka main table) - update only
|
|
||||||
@define('CONST_Tablespace_Place_Data', false);
|
|
||||||
@define('CONST_Tablespace_Place_Index', false);
|
|
||||||
// address computation tables - update only
|
|
||||||
@define('CONST_Tablespace_Address_Data', false);
|
|
||||||
@define('CONST_Tablespace_Address_Index', false);
|
|
||||||
// search tables - needed for lookups
|
|
||||||
@define('CONST_Tablespace_Search_Data', false);
|
|
||||||
@define('CONST_Tablespace_Search_Index', false);
|
|
||||||
// additional data, e.g. TIGER data, type searches - needed for lookups
|
|
||||||
@define('CONST_Tablespace_Aux_Data', false);
|
|
||||||
@define('CONST_Tablespace_Aux_Index', false);
|
|
||||||
|
|
||||||
// Replication settings
|
|
||||||
@define('CONST_Replication_Url', 'http://planet.openstreetmap.org/replication/minute');
|
|
||||||
@define('CONST_Replication_MaxInterval', '3600');
|
|
||||||
@define('CONST_Replication_Update_Interval', '60'); // How often upstream publishes diffs
|
|
||||||
@define('CONST_Replication_Recheck_Interval', '60'); // How long to sleep if no update found yet
|
|
||||||
|
|
||||||
// Connection buckets to rate limit people being nasty
|
|
||||||
@define('CONST_ConnectionBucket_MemcacheServerAddress', false);
|
|
||||||
@define('CONST_ConnectionBucket_MemcacheServerPort', 11211);
|
|
||||||
@define('CONST_ConnectionBucket_MaxBlockList', 100);
|
|
||||||
@define('CONST_ConnectionBucket_LeakRate', 1);
|
|
||||||
@define('CONST_ConnectionBucket_BlockLimit', 10);
|
|
||||||
@define('CONST_ConnectionBucket_WaitLimit', 6);
|
|
||||||
@define('CONST_ConnectionBucket_MaxSleeping', 10);
|
|
||||||
@define('CONST_ConnectionBucket_Cost_Reverse', 1);
|
|
||||||
@define('CONST_ConnectionBucket_Cost_Search', 2);
|
|
||||||
@define('CONST_ConnectionBucket_Cost_Details', 3);
|
|
||||||
@define('CONST_ConnectionBucket_Cost_Status', 1);
|
|
||||||
|
|
||||||
// Override this function to add an adjustment factor to the cost
|
|
||||||
// based on server load. e.g. getBlockingProcesses
|
|
||||||
if (!function_exists('user_busy_cost'))
|
|
||||||
{
|
|
||||||
function user_busy_cost()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Website settings
|
|
||||||
@define('CONST_NoAccessControl', true);
|
|
||||||
@define('CONST_ClosedForIndexing', false);
|
|
||||||
@define('CONST_ClosedForIndexingExceptionIPs', '');
|
|
||||||
@define('CONST_BlockedIPs', '');
|
|
||||||
@define('CONST_BulkUserIPs', '');
|
|
||||||
@define('CONST_BlockMessage', ''); // additional info to show for blocked IPs
|
|
||||||
|
|
||||||
@define('CONST_Website_BaseURL', 'http://'.php_uname('n').'/');
|
|
||||||
@define('CONST_Tile_Default', 'Mapnik');
|
|
||||||
|
|
||||||
@define('CONST_Default_Language', false);
|
|
||||||
@define('CONST_Default_Lat', 20.0);
|
|
||||||
@define('CONST_Default_Lon', 0.0);
|
|
||||||
@define('CONST_Default_Zoom', 2);
|
|
||||||
@define('CONST_Map_Tile_URL', 'http://{s}.tile.osm.org/{z}/{x}/{y}.png');
|
|
||||||
@define('CONST_Map_Tile_Attribution', ''); // Set if tile source isn't osm.org
|
|
||||||
|
|
||||||
@define('CONST_Search_AreaPolygons_Enabled', true);
|
|
||||||
@define('CONST_Search_AreaPolygons', true);
|
|
||||||
|
|
||||||
@define('CONST_Search_BatchMode', false);
|
|
||||||
|
|
||||||
@define('CONST_Search_TryDroppedAddressTerms', false);
|
|
||||||
@define('CONST_Search_NameOnlySearchFrequencyThreshold', 500);
|
|
||||||
// If set to true, then reverse order of queries will be tried by default.
|
|
||||||
// When set to false only selected languages alloow reverse search.
|
|
||||||
@define('CONST_Search_ReversePlanForAll', true);
|
|
||||||
|
|
||||||
@define('CONST_Places_Max_ID_count', 50);
|
|
||||||
|
|
||||||
// Set to zero to disable polygon output
|
|
||||||
@define('CONST_PolygonOutput_MaximumTypes', 1);
|
|
||||||
|
|
||||||
// Log settings
|
|
||||||
@define('CONST_Log_DB', true);
|
|
||||||
@define('CONST_Log_File', false);
|
|
||||||
@define('CONST_Log_File_Format', 'TODO'); // Currently hard coded
|
|
||||||
@define('CONST_Log_File_SearchLog', '');
|
|
||||||
@define('CONST_Log_File_ReverseLog', '');
|
|
||||||
|
|
||||||
|
|
||||||
|
echo "ERROR: Scripts must be run from build directory.\n";
|
||||||
|
exit;
|
||||||
|
|||||||
6
sql/aux_tables.sql
Normal file
6
sql/aux_tables.sql
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
CREATE TABLE location_property_aux () INHERITS (location_property);
|
||||||
|
CREATE INDEX idx_location_property_aux_place_id ON location_property_aux USING BTREE (place_id);
|
||||||
|
CREATE INDEX idx_location_property_aux_parent_place_id ON location_property_aux USING BTREE (parent_place_id);
|
||||||
|
CREATE INDEX idx_location_property_aux_housenumber_parent_place_id ON location_property_aux USING BTREE (parent_place_id, housenumber);
|
||||||
|
GRANT SELECT ON location_property_aux TO "{www-user}";
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -17,11 +17,9 @@ CREATE INDEX idx_placex_parent_place_id ON placex USING BTREE (parent_place_id)
|
|||||||
CREATE INDEX idx_placex_reverse_geometry ON placex USING gist (geometry) {ts:search-index} where rank_search != 28 and (name is not null or housenumber is not null) and class not in ('waterway','railway','tunnel','bridge','man_made');
|
CREATE INDEX idx_placex_reverse_geometry ON placex USING gist (geometry) {ts:search-index} where rank_search != 28 and (name is not null or housenumber is not null) and class not in ('waterway','railway','tunnel','bridge','man_made');
|
||||||
CREATE INDEX idx_location_area_country_place_id ON location_area_country USING BTREE (place_id) {ts:address-index};
|
CREATE INDEX idx_location_area_country_place_id ON location_area_country USING BTREE (place_id) {ts:address-index};
|
||||||
|
|
||||||
CREATE INDEX idx_search_name_country_centroid ON search_name_country USING GIST (centroid) {ts:address-index};
|
CREATE INDEX idx_osmline_parent_place_id ON location_property_osmline USING BTREE (parent_place_id) {ts:search-index};
|
||||||
|
|
||||||
-- start
|
CREATE INDEX idx_search_name_country_centroid ON search_name_country USING GIST (centroid) {ts:address-index};
|
||||||
CREATE INDEX idx_location_property_-partition-_centroid ON location_property_-partition- USING GIST (centroid) {ts:address-index};
|
|
||||||
-- end
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS place_id_idx;
|
DROP INDEX IF EXISTS place_id_idx;
|
||||||
CREATE UNIQUE INDEX idx_place_osm_unique on place using btree(osm_id,osm_type,class,type) {ts:address-index};
|
CREATE UNIQUE INDEX idx_place_osm_unique on place using btree(osm_id,osm_type,class,type) {ts:address-index};
|
||||||
|
|||||||
@@ -6,8 +6,11 @@ TRUNCATE location_area;
|
|||||||
DROP SEQUENCE seq_place;
|
DROP SEQUENCE seq_place;
|
||||||
CREATE SEQUENCE seq_place start 100000;
|
CREATE SEQUENCE seq_place start 100000;
|
||||||
|
|
||||||
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry) select * from place where osm_type = 'N';
|
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry)
|
||||||
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry) select * from place where osm_type = 'W';
|
select osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry from place where osm_type = 'N';
|
||||||
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry) select * from place where osm_type = 'R';
|
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry)
|
||||||
|
select osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry from place where osm_type = 'W';
|
||||||
|
insert into placex (osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry)
|
||||||
|
select osm_type, osm_id, class, type, name, admin_level, housenumber, street, isin, postcode, country_code, extratags, geometry from place where osm_type = 'R';
|
||||||
|
|
||||||
--select count(*) from (select create_interpolation(osm_id, housenumber) from placex where indexed=false and class='place' and type='houses') as x;
|
--select count(*) from (select create_interpolation(osm_id, housenumber) from placex where indexed=false and class='place' and type='houses') as x;
|
||||||
|
|||||||
@@ -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
|
DECLARE
|
||||||
r nearfeaturecentr%rowtype;
|
r nearfeaturecentr%rowtype;
|
||||||
BEGIN
|
BEGIN
|
||||||
@@ -6,14 +6,14 @@ BEGIN
|
|||||||
-- start
|
-- start
|
||||||
IF in_partition = -partition- THEN
|
IF in_partition = -partition- THEN
|
||||||
FOR r IN
|
FOR r IN
|
||||||
SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(point, centroid)) as distance, isguess, centroid FROM (
|
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_Contains(geometry, point) and rank_search < maxrank
|
SELECT * FROM location_area_large_-partition- WHERE ST_Intersects(geometry, feature) and rank_search < maxrank
|
||||||
UNION ALL
|
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
|
) as location_area
|
||||||
GROUP BY place_id, keywords, rank_address, rank_search, isguess, centroid
|
GROUP BY place_id, keywords, rank_address, rank_search, isguess, centroid
|
||||||
ORDER BY rank_address, isin_tokens && keywords desc, isguess asc,
|
ORDER BY rank_address, isin_tokens && keywords desc, isguess asc,
|
||||||
ST_Distance(point, centroid) *
|
ST_Distance(feature, centroid) *
|
||||||
CASE
|
CASE
|
||||||
WHEN rank_address = 16 AND rank_search = 15 THEN 0.2 -- capital city
|
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
|
WHEN rank_address = 16 AND rank_search = 16 THEN 0.25 -- city
|
||||||
@@ -65,13 +65,15 @@ BEGIN
|
|||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
IF in_rank_search <= 4 THEN
|
IF in_rank_search <= 4 THEN
|
||||||
INSERT INTO location_area_country values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
|
INSERT INTO location_area_country (partition, place_id, country_code, keywords, rank_search, rank_address, isguess, centroid, geometry)
|
||||||
|
values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
|
||||||
RETURN TRUE;
|
RETURN TRUE;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- start
|
-- start
|
||||||
IF in_partition = -partition- THEN
|
IF in_partition = -partition- THEN
|
||||||
INSERT INTO location_area_large_-partition- values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
|
INSERT INTO location_area_large_-partition- (partition, place_id, country_code, keywords, rank_search, rank_address, isguess, centroid, geometry)
|
||||||
|
values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
|
||||||
RETURN TRUE;
|
RETURN TRUE;
|
||||||
END IF;
|
END IF;
|
||||||
-- end
|
-- end
|
||||||
@@ -203,14 +205,14 @@ DECLARE
|
|||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
DELETE FROM search_name WHERE place_id = in_place_id;
|
DELETE FROM search_name WHERE place_id = in_place_id;
|
||||||
INSERT INTO search_name values (in_place_id, in_rank_search, in_rank_address, in_importance, in_country_code,
|
INSERT INTO search_name (place_id, search_rank, address_rank, importance, country_code, name_vector, nameaddress_vector, centroid)
|
||||||
in_name_vector, in_nameaddress_vector, in_centroid);
|
values (in_place_id, in_rank_search, in_rank_address, in_importance, in_country_code, in_name_vector, in_nameaddress_vector, in_centroid);
|
||||||
|
|
||||||
IF in_rank_search <= 4 THEN
|
IF in_rank_search <= 4 THEN
|
||||||
DELETE FROM search_name_country WHERE place_id = in_place_id;
|
DELETE FROM search_name_country WHERE place_id = in_place_id;
|
||||||
IF in_rank_address > 0 THEN
|
IF in_rank_address > 0 THEN
|
||||||
INSERT INTO search_name_country values (in_place_id, in_rank_search, in_rank_address,
|
INSERT INTO search_name_country (place_id, search_rank, address_rank, name_vector, centroid)
|
||||||
in_name_vector, in_geometry);
|
values (in_place_id, in_rank_search, in_rank_address, in_name_vector, in_geometry);
|
||||||
END IF;
|
END IF;
|
||||||
RETURN TRUE;
|
RETURN TRUE;
|
||||||
END IF;
|
END IF;
|
||||||
@@ -219,8 +221,8 @@ BEGIN
|
|||||||
IF in_partition = -partition- THEN
|
IF in_partition = -partition- THEN
|
||||||
DELETE FROM search_name_-partition- values WHERE place_id = in_place_id;
|
DELETE FROM search_name_-partition- values WHERE place_id = in_place_id;
|
||||||
IF in_rank_address > 0 THEN
|
IF in_rank_address > 0 THEN
|
||||||
INSERT INTO search_name_-partition- values (in_place_id, in_rank_search, in_rank_address,
|
INSERT INTO search_name_-partition- (place_id, search_rank, address_rank, name_vector, centroid)
|
||||||
in_name_vector, in_geometry);
|
values (in_place_id, in_rank_search, in_rank_address, in_name_vector, in_geometry);
|
||||||
END IF;
|
END IF;
|
||||||
RETURN TRUE;
|
RETURN TRUE;
|
||||||
END IF;
|
END IF;
|
||||||
@@ -261,7 +263,8 @@ BEGIN
|
|||||||
-- start
|
-- start
|
||||||
IF in_partition = -partition- THEN
|
IF in_partition = -partition- THEN
|
||||||
DELETE FROM location_road_-partition- where place_id = in_place_id;
|
DELETE FROM location_road_-partition- where place_id = in_place_id;
|
||||||
INSERT INTO location_road_-partition- values (in_partition, in_place_id, in_country_code, in_geometry);
|
INSERT INTO location_road_-partition- (partition, place_id, country_code, geometry)
|
||||||
|
values (in_partition, in_place_id, in_country_code, in_geometry);
|
||||||
RETURN TRUE;
|
RETURN TRUE;
|
||||||
END IF;
|
END IF;
|
||||||
-- end
|
-- end
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ drop type if exists nearfeature cascade;
|
|||||||
create type nearfeature as (
|
create type nearfeature as (
|
||||||
place_id BIGINT,
|
place_id BIGINT,
|
||||||
keywords int[],
|
keywords int[],
|
||||||
rank_address integer,
|
rank_address smallint,
|
||||||
rank_search integer,
|
rank_search smallint,
|
||||||
distance float,
|
distance float,
|
||||||
isguess boolean
|
isguess boolean
|
||||||
);
|
);
|
||||||
@@ -17,8 +17,8 @@ drop type if exists nearfeaturecentr cascade;
|
|||||||
create type nearfeaturecentr as (
|
create type nearfeaturecentr as (
|
||||||
place_id BIGINT,
|
place_id BIGINT,
|
||||||
keywords int[],
|
keywords int[],
|
||||||
rank_address integer,
|
rank_address smallint,
|
||||||
rank_search integer,
|
rank_search smallint,
|
||||||
distance float,
|
distance float,
|
||||||
isguess boolean,
|
isguess boolean,
|
||||||
centroid GEOMETRY
|
centroid GEOMETRY
|
||||||
@@ -27,8 +27,8 @@ create type nearfeaturecentr as (
|
|||||||
drop table IF EXISTS search_name_blank CASCADE;
|
drop table IF EXISTS search_name_blank CASCADE;
|
||||||
CREATE TABLE search_name_blank (
|
CREATE TABLE search_name_blank (
|
||||||
place_id BIGINT,
|
place_id BIGINT,
|
||||||
search_rank integer,
|
search_rank smallint,
|
||||||
address_rank integer,
|
address_rank smallint,
|
||||||
name_vector integer[]
|
name_vector integer[]
|
||||||
);
|
);
|
||||||
SELECT AddGeometryColumn('search_name_blank', 'centroid', 4326, 'GEOMETRY', 2);
|
SELECT AddGeometryColumn('search_name_blank', 'centroid', 4326, 'GEOMETRY', 2);
|
||||||
@@ -51,14 +51,9 @@ CREATE INDEX idx_search_name_-partition-_place_id ON search_name_-partition- USI
|
|||||||
CREATE INDEX idx_search_name_-partition-_centroid ON search_name_-partition- USING GIST (centroid) {ts:address-index};
|
CREATE INDEX idx_search_name_-partition-_centroid ON search_name_-partition- USING GIST (centroid) {ts:address-index};
|
||||||
CREATE INDEX idx_search_name_-partition-_name_vector ON search_name_-partition- USING GIN (name_vector) WITH (fastupdate = off) {ts:address-index};
|
CREATE INDEX idx_search_name_-partition-_name_vector ON search_name_-partition- USING GIN (name_vector) WITH (fastupdate = off) {ts:address-index};
|
||||||
|
|
||||||
CREATE TABLE location_property_-partition- () INHERITS (location_property) {ts:aux-data};
|
|
||||||
CREATE INDEX idx_location_property_-partition-_place_id ON location_property_-partition- USING BTREE (place_id) {ts:aux-index};
|
|
||||||
CREATE INDEX idx_location_property_-partition-_parent_place_id ON location_property_-partition- USING BTREE (parent_place_id) {ts:aux-index};
|
|
||||||
CREATE INDEX idx_location_property_-partition-_housenumber_parent_place_id ON location_property_-partition- USING BTREE (parent_place_id, housenumber) {ts:aux-index};
|
|
||||||
|
|
||||||
CREATE TABLE location_road_-partition- (
|
CREATE TABLE location_road_-partition- (
|
||||||
partition integer,
|
|
||||||
place_id BIGINT,
|
place_id BIGINT,
|
||||||
|
partition SMALLINT,
|
||||||
country_code VARCHAR(2)
|
country_code VARCHAR(2)
|
||||||
) {ts:address-data};
|
) {ts:address-data};
|
||||||
SELECT AddGeometryColumn('location_road_-partition-', 'geometry', 4326, 'GEOMETRY', 2);
|
SELECT AddGeometryColumn('location_road_-partition-', 'geometry', 4326, 'GEOMETRY', 2);
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
-- Splits the line at the given point and returns the two parts
|
|
||||||
-- in a multilinestring.
|
|
||||||
CREATE OR REPLACE FUNCTION split_line_on_node(line GEOMETRY, point GEOMETRY)
|
|
||||||
RETURNS GEOMETRY
|
|
||||||
AS $$
|
|
||||||
DECLARE
|
|
||||||
frac FLOAT;
|
|
||||||
BEGIN
|
|
||||||
frac := ST_Line_Locate_Point(line, point);
|
|
||||||
RETURN ST_Collect(ST_Line_Substring(line, 0, frac),
|
|
||||||
ST_Line_Substring(line, frac, 1));
|
|
||||||
END
|
|
||||||
$$
|
|
||||||
LANGUAGE plpgsql;
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
-- Splits the line at the given point and returns the two parts
|
|
||||||
-- in a multilinestring.
|
|
||||||
CREATE OR REPLACE FUNCTION split_line_on_node(line GEOMETRY, point GEOMETRY)
|
|
||||||
RETURNS GEOMETRY
|
|
||||||
AS $$
|
|
||||||
BEGIN
|
|
||||||
RETURN ST_Split(ST_Snap(line, point, 0.0005), point);
|
|
||||||
END;
|
|
||||||
$$
|
|
||||||
LANGUAGE plpgsql;
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
drop table import_npi_log;
|
|
||||||
CREATE TABLE import_npi_log (
|
|
||||||
npiid integer,
|
|
||||||
batchend timestamp,
|
|
||||||
batchsize integer,
|
|
||||||
starttime timestamp,
|
|
||||||
endtime timestamp,
|
|
||||||
event text
|
|
||||||
);
|
|
||||||
|
|
||||||
drop table IF EXISTS word;
|
|
||||||
CREATE TABLE word (
|
|
||||||
word_id INTEGER,
|
|
||||||
word_token text,
|
|
||||||
word_trigram text,
|
|
||||||
word text,
|
|
||||||
class text,
|
|
||||||
type text,
|
|
||||||
country_code varchar(2),
|
|
||||||
search_name_count INTEGER,
|
|
||||||
operator TEXT
|
|
||||||
);
|
|
||||||
SELECT AddGeometryColumn('word', 'location', 4326, 'GEOMETRY', 2);
|
|
||||||
CREATE INDEX idx_word_word_id on word USING BTREE (word_id);
|
|
||||||
CREATE INDEX idx_word_word_token on word USING BTREE (word_token);
|
|
||||||
GRANT SELECT ON word TO "www-data" ;
|
|
||||||
DROP SEQUENCE seq_word;
|
|
||||||
CREATE SEQUENCE seq_word start 1;
|
|
||||||
|
|
||||||
drop table IF EXISTS location_property CASCADE;
|
|
||||||
CREATE TABLE location_property (
|
|
||||||
place_id BIGINT,
|
|
||||||
partition integer,
|
|
||||||
parent_place_id BIGINT,
|
|
||||||
housenumber TEXT,
|
|
||||||
postcode TEXT
|
|
||||||
);
|
|
||||||
SELECT AddGeometryColumn('location_property', 'centroid', 4326, 'POINT', 2);
|
|
||||||
|
|
||||||
CREATE TABLE location_property_aux () INHERITS (location_property);
|
|
||||||
CREATE INDEX idx_location_property_aux_place_id ON location_property_aux USING BTREE (place_id);
|
|
||||||
CREATE INDEX idx_location_property_aux_parent_place_id ON location_property_aux USING BTREE (parent_place_id);
|
|
||||||
CREATE INDEX idx_location_property_aux_housenumber_parent_place_id ON location_property_aux USING BTREE (parent_place_id, housenumber);
|
|
||||||
|
|
||||||
CREATE TABLE location_property_tiger () INHERITS (location_property);
|
|
||||||
CREATE INDEX idx_location_property_tiger_place_id ON location_property_tiger USING BTREE (place_id);
|
|
||||||
CREATE INDEX idx_location_property_tiger_parent_place_id ON location_property_tiger USING BTREE (parent_place_id);
|
|
||||||
CREATE INDEX idx_location_property_tiger_housenumber_parent_place_id ON location_property_tiger USING BTREE (parent_place_id, housenumber);
|
|
||||||
|
|
||||||
drop table IF EXISTS search_name_blank CASCADE;
|
|
||||||
CREATE TABLE search_name_blank (
|
|
||||||
place_id BIGINT,
|
|
||||||
search_rank integer,
|
|
||||||
address_rank integer,
|
|
||||||
importance FLOAT,
|
|
||||||
country_code varchar(2),
|
|
||||||
name_vector integer[],
|
|
||||||
nameaddress_vector integer[]
|
|
||||||
);
|
|
||||||
SELECT AddGeometryColumn('search_name_blank', 'centroid', 4326, 'GEOMETRY', 2);
|
|
||||||
|
|
||||||
drop table IF EXISTS search_name;
|
|
||||||
CREATE TABLE search_name () INHERITS (search_name_blank);
|
|
||||||
CREATE INDEX search_name_name_vector_idx ON search_name USING GIN (name_vector gin__int_ops) WITH (fastupdate = off);
|
|
||||||
CREATE INDEX searchnameplacesearch_search_nameaddress_vector_idx ON search_name USING GIN (nameaddress_vector gin__int_ops) WITH (fastupdate = off);
|
|
||||||
CREATE INDEX idx_search_name_centroid ON search_name USING GIST (centroid);
|
|
||||||
CREATE INDEX idx_search_name_place_id ON search_name USING BTREE (place_id);
|
|
||||||
|
|
||||||
drop table IF EXISTS place_addressline;
|
|
||||||
CREATE TABLE place_addressline (
|
|
||||||
place_id BIGINT,
|
|
||||||
address_place_id BIGINT,
|
|
||||||
fromarea boolean,
|
|
||||||
isaddress boolean,
|
|
||||||
distance float,
|
|
||||||
cached_rank_address integer
|
|
||||||
);
|
|
||||||
CREATE INDEX idx_place_addressline_place_id on place_addressline USING BTREE (place_id);
|
|
||||||
CREATE INDEX idx_place_addressline_address_place_id on place_addressline USING BTREE (address_place_id);
|
|
||||||
|
|
||||||
drop table IF EXISTS place_boundingbox CASCADE;
|
|
||||||
CREATE TABLE place_boundingbox (
|
|
||||||
place_id BIGINT,
|
|
||||||
minlat float,
|
|
||||||
maxlat float,
|
|
||||||
minlon float,
|
|
||||||
maxlon float,
|
|
||||||
numfeatures integer,
|
|
||||||
area float
|
|
||||||
);
|
|
||||||
CREATE INDEX idx_place_boundingbox_place_id on place_boundingbox USING BTREE (place_id);
|
|
||||||
SELECT AddGeometryColumn('place_boundingbox', 'outline', 4326, 'GEOMETRY', 2);
|
|
||||||
CREATE INDEX idx_place_boundingbox_outline ON place_boundingbox USING GIST (outline);
|
|
||||||
GRANT SELECT on place_boundingbox to "www-data" ;
|
|
||||||
GRANT INSERT on place_boundingbox to "www-data" ;
|
|
||||||
|
|
||||||
drop table country;
|
|
||||||
CREATE TABLE country (
|
|
||||||
country_code varchar(2),
|
|
||||||
country_name hstore,
|
|
||||||
country_default_language_code varchar(2)
|
|
||||||
);
|
|
||||||
SELECT AddGeometryColumn('country', 'geometry', 4326, 'POLYGON', 2);
|
|
||||||
insert into country select iso3166::varchar(2), 'name:en'->cntry_name, null,
|
|
||||||
ST_Transform(geometryn(the_geom, generate_series(1, numgeometries(the_geom))), 4326) from worldboundaries;
|
|
||||||
CREATE INDEX idx_country_country_code ON country USING BTREE (country_code);
|
|
||||||
CREATE INDEX idx_country_geometry ON country USING GIST (geometry);
|
|
||||||
|
|
||||||
drop table placex;
|
|
||||||
CREATE TABLE placex (
|
|
||||||
place_id BIGINT NOT NULL,
|
|
||||||
partition integer,
|
|
||||||
osm_type char(1),
|
|
||||||
osm_id INTEGER,
|
|
||||||
class TEXT NOT NULL,
|
|
||||||
type TEXT NOT NULL,
|
|
||||||
name HSTORE,
|
|
||||||
admin_level INTEGER,
|
|
||||||
housenumber TEXT,
|
|
||||||
street TEXT,
|
|
||||||
isin TEXT,
|
|
||||||
postcode TEXT,
|
|
||||||
country_code varchar(2),
|
|
||||||
extratags HSTORE,
|
|
||||||
parent_place_id BIGINT,
|
|
||||||
linked_place_id BIGINT,
|
|
||||||
rank_address INTEGER,
|
|
||||||
rank_search INTEGER,
|
|
||||||
importance FLOAT,
|
|
||||||
indexed_status INTEGER,
|
|
||||||
indexed_date TIMESTAMP,
|
|
||||||
geometry_sector INTEGER
|
|
||||||
);
|
|
||||||
SELECT AddGeometryColumn('placex', 'geometry', 4326, 'GEOMETRY', 2);
|
|
||||||
CREATE UNIQUE INDEX idx_place_id ON placex USING BTREE (place_id);
|
|
||||||
CREATE INDEX idx_placex_osmid ON placex USING BTREE (osm_type, osm_id);
|
|
||||||
CREATE INDEX idx_placex_rank_search ON placex USING BTREE (rank_search);
|
|
||||||
CREATE INDEX idx_placex_rank_address ON placex USING BTREE (rank_address);
|
|
||||||
CREATE INDEX idx_placex_geometry ON placex USING GIST (geometry);
|
|
||||||
CREATE INDEX idx_placex_parent_place_id ON placex USING BTREE (parent_place_id) where parent_place_id IS NOT NULL;
|
|
||||||
|
|
||||||
DROP SEQUENCE seq_place;
|
|
||||||
CREATE SEQUENCE seq_place start 1;
|
|
||||||
GRANT SELECT on placex to "www-data" ;
|
|
||||||
GRANT UPDATE ON placex to "www-data" ;
|
|
||||||
GRANT SELECT ON search_name to "www-data" ;
|
|
||||||
GRANT DELETE on search_name to "www-data" ;
|
|
||||||
GRANT INSERT on search_name to "www-data" ;
|
|
||||||
GRANT SELECT on place_addressline to "www-data" ;
|
|
||||||
GRANT INSERT ON place_addressline to "www-data" ;
|
|
||||||
GRANT DELETE on place_addressline to "www-data" ;
|
|
||||||
GRANT SELECT ON seq_word to "www-data" ;
|
|
||||||
GRANT UPDATE ON seq_word to "www-data" ;
|
|
||||||
GRANT INSERT ON word to "www-data" ;
|
|
||||||
GRANT SELECT on country to "www-data" ;
|
|
||||||
131
sql/tables.sql
131
sql/tables.sql
@@ -1,41 +1,21 @@
|
|||||||
drop table if exists import_status;
|
drop table if exists import_status;
|
||||||
CREATE TABLE import_status (
|
CREATE TABLE import_status (
|
||||||
lastimportdate timestamp NOT NULL
|
lastimportdate timestamp NOT NULL,
|
||||||
|
sequence_id integer,
|
||||||
|
indexed boolean
|
||||||
);
|
);
|
||||||
GRANT SELECT ON import_status TO "{www-user}" ;
|
GRANT SELECT ON import_status TO "{www-user}" ;
|
||||||
|
|
||||||
drop table if exists import_osmosis_log;
|
drop table if exists import_osmosis_log;
|
||||||
CREATE TABLE import_osmosis_log (
|
CREATE TABLE import_osmosis_log (
|
||||||
batchend timestamp,
|
batchend timestamp,
|
||||||
|
batchseq integer,
|
||||||
batchsize integer,
|
batchsize integer,
|
||||||
starttime timestamp,
|
starttime timestamp,
|
||||||
endtime timestamp,
|
endtime timestamp,
|
||||||
event text
|
event text
|
||||||
);
|
);
|
||||||
|
|
||||||
drop table if exists import_npi_log;
|
|
||||||
CREATE TABLE import_npi_log (
|
|
||||||
npiid integer,
|
|
||||||
batchend timestamp,
|
|
||||||
batchsize integer,
|
|
||||||
starttime timestamp,
|
|
||||||
endtime timestamp,
|
|
||||||
event text
|
|
||||||
);
|
|
||||||
|
|
||||||
--drop table IF EXISTS query_log;
|
|
||||||
CREATE TABLE query_log (
|
|
||||||
starttime timestamp,
|
|
||||||
query text,
|
|
||||||
ipaddress text,
|
|
||||||
endtime timestamp,
|
|
||||||
results integer
|
|
||||||
);
|
|
||||||
CREATE INDEX idx_query_log ON query_log USING BTREE (starttime);
|
|
||||||
GRANT SELECT ON query_log TO "{www-user}" ;
|
|
||||||
GRANT INSERT ON query_log TO "{www-user}" ;
|
|
||||||
GRANT UPDATE ON query_log TO "{www-user}" ;
|
|
||||||
|
|
||||||
CREATE TABLE new_query_log (
|
CREATE TABLE new_query_log (
|
||||||
type text,
|
type text,
|
||||||
starttime timestamp,
|
starttime timestamp,
|
||||||
@@ -43,6 +23,7 @@ CREATE TABLE new_query_log (
|
|||||||
useragent text,
|
useragent text,
|
||||||
language text,
|
language text,
|
||||||
query text,
|
query text,
|
||||||
|
searchterm text,
|
||||||
endtime timestamp,
|
endtime timestamp,
|
||||||
results integer,
|
results integer,
|
||||||
format text,
|
format text,
|
||||||
@@ -56,9 +37,6 @@ GRANT SELECT ON new_query_log TO "{www-user}" ;
|
|||||||
GRANT SELECT ON TABLE country_name TO "{www-user}";
|
GRANT SELECT ON TABLE country_name TO "{www-user}";
|
||||||
GRANT SELECT ON TABLE gb_postcode TO "{www-user}";
|
GRANT SELECT ON TABLE gb_postcode TO "{www-user}";
|
||||||
|
|
||||||
create view vw_search_query_log as SELECT substr(query, 1, 50) AS query, starttime, endtime - starttime AS duration, substr(useragent, 1, 20) as
|
|
||||||
useragent, language, results, ipaddress FROM new_query_log WHERE type = 'search' ORDER BY starttime DESC;
|
|
||||||
|
|
||||||
drop table IF EXISTS word;
|
drop table IF EXISTS word;
|
||||||
CREATE TABLE word (
|
CREATE TABLE word (
|
||||||
word_id INTEGER,
|
word_id INTEGER,
|
||||||
@@ -77,12 +55,12 @@ CREATE SEQUENCE seq_word start 1;
|
|||||||
|
|
||||||
drop table IF EXISTS location_area CASCADE;
|
drop table IF EXISTS location_area CASCADE;
|
||||||
CREATE TABLE location_area (
|
CREATE TABLE location_area (
|
||||||
partition integer,
|
|
||||||
place_id BIGINT,
|
place_id BIGINT,
|
||||||
country_code VARCHAR(2),
|
|
||||||
keywords INTEGER[],
|
keywords INTEGER[],
|
||||||
rank_search INTEGER NOT NULL,
|
partition SMALLINT,
|
||||||
rank_address INTEGER NOT NULL,
|
rank_search SMALLINT NOT NULL,
|
||||||
|
rank_address SMALLINT NOT NULL,
|
||||||
|
country_code VARCHAR(2),
|
||||||
isguess BOOL
|
isguess BOOL
|
||||||
);
|
);
|
||||||
SELECT AddGeometryColumn('location_area', 'centroid', 4326, 'POINT', 2);
|
SELECT AddGeometryColumn('location_area', 'centroid', 4326, 'POINT', 2);
|
||||||
@@ -93,8 +71,8 @@ CREATE TABLE location_area_large () INHERITS (location_area);
|
|||||||
drop table IF EXISTS location_property CASCADE;
|
drop table IF EXISTS location_property CASCADE;
|
||||||
CREATE TABLE location_property (
|
CREATE TABLE location_property (
|
||||||
place_id BIGINT,
|
place_id BIGINT,
|
||||||
partition integer,
|
|
||||||
parent_place_id BIGINT,
|
parent_place_id BIGINT,
|
||||||
|
partition SMALLINT,
|
||||||
housenumber TEXT,
|
housenumber TEXT,
|
||||||
postcode TEXT
|
postcode TEXT
|
||||||
);
|
);
|
||||||
@@ -106,21 +84,48 @@ CREATE INDEX idx_location_property_aux_parent_place_id ON location_property_aux
|
|||||||
CREATE INDEX idx_location_property_aux_housenumber_parent_place_id ON location_property_aux USING BTREE (parent_place_id, housenumber);
|
CREATE INDEX idx_location_property_aux_housenumber_parent_place_id ON location_property_aux USING BTREE (parent_place_id, housenumber);
|
||||||
GRANT SELECT ON location_property_aux TO "{www-user}";
|
GRANT SELECT ON location_property_aux TO "{www-user}";
|
||||||
|
|
||||||
CREATE TABLE location_property_tiger () INHERITS (location_property) {ts:aux-data};
|
CREATE TABLE location_property_tiger (
|
||||||
CREATE INDEX idx_location_property_tiger_place_id ON location_property_tiger USING BTREE (place_id) {ts:aux-index};
|
place_id BIGINT,
|
||||||
CREATE INDEX idx_location_property_tiger_parent_place_id ON location_property_tiger USING BTREE (parent_place_id) {ts:aux-index};
|
parent_place_id BIGINT,
|
||||||
CREATE INDEX idx_location_property_tiger_housenumber_parent_place_id ON location_property_tiger USING BTREE (parent_place_id, housenumber) {ts:aux-index};
|
startnumber INTEGER,
|
||||||
|
endnumber INTEGER,
|
||||||
|
partition SMALLINT,
|
||||||
|
linegeo GEOMETRY,
|
||||||
|
interpolationtype TEXT,
|
||||||
|
postcode TEXT);
|
||||||
GRANT SELECT ON location_property_tiger TO "{www-user}";
|
GRANT SELECT ON location_property_tiger TO "{www-user}";
|
||||||
|
|
||||||
|
drop table if exists location_property_osmline;
|
||||||
|
CREATE TABLE location_property_osmline (
|
||||||
|
place_id BIGINT NOT NULL,
|
||||||
|
osm_id BIGINT,
|
||||||
|
parent_place_id BIGINT,
|
||||||
|
geometry_sector INTEGER,
|
||||||
|
indexed_date TIMESTAMP,
|
||||||
|
startnumber INTEGER,
|
||||||
|
endnumber INTEGER,
|
||||||
|
partition SMALLINT,
|
||||||
|
indexed_status SMALLINT,
|
||||||
|
linegeo GEOMETRY,
|
||||||
|
interpolationtype TEXT,
|
||||||
|
address HSTORE,
|
||||||
|
postcode TEXT,
|
||||||
|
country_code VARCHAR(2)
|
||||||
|
){ts:search-data};
|
||||||
|
CREATE UNIQUE INDEX idx_osmline_place_id ON location_property_osmline USING BTREE (place_id) {ts:search-index};
|
||||||
|
CREATE INDEX idx_osmline_geometry_sector ON location_property_osmline USING BTREE (geometry_sector) {ts:address-index};
|
||||||
|
CREATE INDEX idx_osmline_linegeo ON location_property_osmline USING GIST (linegeo) {ts:search-index};
|
||||||
|
GRANT SELECT ON location_property_osmline TO "{www-user}";
|
||||||
|
|
||||||
drop table IF EXISTS search_name;
|
drop table IF EXISTS search_name;
|
||||||
CREATE TABLE search_name (
|
CREATE TABLE search_name (
|
||||||
place_id BIGINT,
|
place_id BIGINT,
|
||||||
search_rank integer,
|
|
||||||
address_rank integer,
|
|
||||||
importance FLOAT,
|
importance FLOAT,
|
||||||
country_code varchar(2),
|
search_rank SMALLINT,
|
||||||
|
address_rank SMALLINT,
|
||||||
name_vector integer[],
|
name_vector integer[],
|
||||||
nameaddress_vector integer[]
|
nameaddress_vector integer[],
|
||||||
|
country_code varchar(2)
|
||||||
) {ts:search-data};
|
) {ts:search-data};
|
||||||
SELECT AddGeometryColumn('search_name', 'centroid', 4326, 'GEOMETRY', 2);
|
SELECT AddGeometryColumn('search_name', 'centroid', 4326, 'GEOMETRY', 2);
|
||||||
CREATE INDEX idx_search_name_place_id ON search_name USING BTREE (place_id) {ts:search-index};
|
CREATE INDEX idx_search_name_place_id ON search_name USING BTREE (place_id) {ts:search-index};
|
||||||
@@ -129,33 +134,35 @@ drop table IF EXISTS place_addressline;
|
|||||||
CREATE TABLE place_addressline (
|
CREATE TABLE place_addressline (
|
||||||
place_id BIGINT,
|
place_id BIGINT,
|
||||||
address_place_id BIGINT,
|
address_place_id BIGINT,
|
||||||
|
distance FLOAT,
|
||||||
|
cached_rank_address SMALLINT,
|
||||||
fromarea boolean,
|
fromarea boolean,
|
||||||
isaddress boolean,
|
isaddress boolean
|
||||||
distance float,
|
|
||||||
cached_rank_address integer
|
|
||||||
) {ts:search-data};
|
) {ts:search-data};
|
||||||
CREATE INDEX idx_place_addressline_place_id on place_addressline USING BTREE (place_id) {ts:search-index};
|
CREATE INDEX idx_place_addressline_place_id on place_addressline USING BTREE (place_id) {ts:search-index};
|
||||||
|
|
||||||
drop table if exists placex;
|
drop table if exists placex;
|
||||||
CREATE TABLE placex (
|
CREATE TABLE placex (
|
||||||
place_id BIGINT NOT NULL,
|
place_id BIGINT NOT NULL,
|
||||||
partition integer,
|
|
||||||
LIKE place INCLUDING CONSTRAINTS,
|
|
||||||
parent_place_id BIGINT,
|
parent_place_id BIGINT,
|
||||||
linked_place_id BIGINT,
|
linked_place_id BIGINT,
|
||||||
rank_address INTEGER,
|
|
||||||
rank_search INTEGER,
|
|
||||||
importance FLOAT,
|
importance FLOAT,
|
||||||
indexed_status INTEGER,
|
|
||||||
indexed_date TIMESTAMP,
|
indexed_date TIMESTAMP,
|
||||||
wikipedia TEXT, -- calculated wikipedia article name (language:title)
|
|
||||||
geometry_sector INTEGER,
|
geometry_sector INTEGER,
|
||||||
calculated_country_code varchar(2)
|
rank_address SMALLINT,
|
||||||
|
rank_search SMALLINT,
|
||||||
|
partition SMALLINT,
|
||||||
|
indexed_status SMALLINT,
|
||||||
|
LIKE place INCLUDING CONSTRAINTS,
|
||||||
|
wikipedia TEXT, -- calculated wikipedia article name (language:title)
|
||||||
|
country_code varchar(2),
|
||||||
|
housenumber TEXT,
|
||||||
|
postcode TEXT
|
||||||
) {ts:search-data};
|
) {ts:search-data};
|
||||||
SELECT AddGeometryColumn('placex', 'centroid', 4326, 'GEOMETRY', 2);
|
SELECT AddGeometryColumn('placex', 'centroid', 4326, 'GEOMETRY', 2);
|
||||||
CREATE UNIQUE INDEX idx_place_id ON placex USING BTREE (place_id) {ts:search-index};
|
CREATE UNIQUE INDEX idx_place_id ON placex USING BTREE (place_id) {ts:search-index};
|
||||||
CREATE INDEX idx_placex_osmid ON placex USING BTREE (osm_type, osm_id) {ts:search-index};
|
CREATE INDEX idx_placex_osmid ON placex USING BTREE (osm_type, osm_id) {ts:search-index};
|
||||||
CREATE INDEX idx_placex_linked_place_id ON placex USING BTREE (linked_place_id) {ts:address-index};
|
CREATE INDEX idx_placex_linked_place_id ON placex USING BTREE (linked_place_id) {ts:address-index} WHERE linked_place_id IS NOT NULL;
|
||||||
CREATE INDEX idx_placex_rank_search ON placex USING BTREE (rank_search, geometry_sector) {ts:address-index};
|
CREATE INDEX idx_placex_rank_search ON placex USING BTREE (rank_search, geometry_sector) {ts:address-index};
|
||||||
CREATE INDEX idx_placex_geometry ON placex USING GIST (geometry) {ts:search-index};
|
CREATE INDEX idx_placex_geometry ON placex USING GIST (geometry) {ts:search-index};
|
||||||
CREATE INDEX idx_placex_adminname on placex USING BTREE (make_standard_name(name->'name'),rank_search) {ts:address-index} WHERE osm_type='N' and rank_search < 26;
|
CREATE INDEX idx_placex_adminname on placex USING BTREE (make_standard_name(name->'name'),rank_search) {ts:address-index} WHERE osm_type='N' and rank_search < 26;
|
||||||
@@ -170,13 +177,17 @@ GRANT SELECT ON planet_osm_ways to "{www-user}" ;
|
|||||||
GRANT SELECT ON planet_osm_rels to "{www-user}" ;
|
GRANT SELECT ON planet_osm_rels to "{www-user}" ;
|
||||||
GRANT SELECT on location_area to "{www-user}" ;
|
GRANT SELECT on location_area to "{www-user}" ;
|
||||||
|
|
||||||
-- insert creates the location tagbles, creates location indexes if indexed == true
|
-- insert creates the location tables, creates location indexes if indexed == true
|
||||||
CREATE TRIGGER placex_before_insert BEFORE INSERT ON placex
|
CREATE TRIGGER placex_before_insert BEFORE INSERT ON placex
|
||||||
FOR EACH ROW EXECUTE PROCEDURE placex_insert();
|
FOR EACH ROW EXECUTE PROCEDURE placex_insert();
|
||||||
|
CREATE TRIGGER osmline_before_insert BEFORE INSERT ON location_property_osmline
|
||||||
|
FOR EACH ROW EXECUTE PROCEDURE osmline_insert();
|
||||||
|
|
||||||
-- update insert creates the location tables
|
-- update insert creates the location tables
|
||||||
CREATE TRIGGER placex_before_update BEFORE UPDATE ON placex
|
CREATE TRIGGER placex_before_update BEFORE UPDATE ON placex
|
||||||
FOR EACH ROW EXECUTE PROCEDURE placex_update();
|
FOR EACH ROW EXECUTE PROCEDURE placex_update();
|
||||||
|
CREATE TRIGGER osmline_before_update BEFORE UPDATE ON location_property_osmline
|
||||||
|
FOR EACH ROW EXECUTE PROCEDURE osmline_update();
|
||||||
|
|
||||||
-- diff update triggers
|
-- diff update triggers
|
||||||
CREATE TRIGGER placex_before_delete AFTER DELETE ON placex
|
CREATE TRIGGER placex_before_delete AFTER DELETE ON placex
|
||||||
@@ -186,13 +197,13 @@ CREATE TRIGGER place_before_delete BEFORE DELETE ON place
|
|||||||
CREATE TRIGGER place_before_insert BEFORE INSERT ON place
|
CREATE TRIGGER place_before_insert BEFORE INSERT ON place
|
||||||
FOR EACH ROW EXECUTE PROCEDURE place_insert();
|
FOR EACH ROW EXECUTE PROCEDURE place_insert();
|
||||||
|
|
||||||
DROP SEQUENCE seq_postcodes;
|
DROP SEQUENCE IF EXISTS seq_postcodes;
|
||||||
CREATE SEQUENCE seq_postcodes start 1;
|
CREATE SEQUENCE seq_postcodes start 1;
|
||||||
|
|
||||||
drop table import_polygon_error;
|
DROP TABLE IF EXISTS import_polygon_error;
|
||||||
CREATE TABLE import_polygon_error (
|
CREATE TABLE import_polygon_error (
|
||||||
osm_type char(1),
|
osm_id BIGINT,
|
||||||
osm_id INTEGER,
|
osm_type CHAR(1),
|
||||||
class TEXT NOT NULL,
|
class TEXT NOT NULL,
|
||||||
type TEXT NOT NULL,
|
type TEXT NOT NULL,
|
||||||
name HSTORE,
|
name HSTORE,
|
||||||
@@ -205,17 +216,17 @@ SELECT AddGeometryColumn('import_polygon_error', 'newgeometry', 4326, 'GEOMETRY'
|
|||||||
CREATE INDEX idx_import_polygon_error_osmid ON import_polygon_error USING BTREE (osm_type, osm_id);
|
CREATE INDEX idx_import_polygon_error_osmid ON import_polygon_error USING BTREE (osm_type, osm_id);
|
||||||
GRANT SELECT ON import_polygon_error TO "{www-user}";
|
GRANT SELECT ON import_polygon_error TO "{www-user}";
|
||||||
|
|
||||||
drop table import_polygon_delete;
|
DROP TABLE IF EXISTS import_polygon_delete;
|
||||||
CREATE TABLE import_polygon_delete (
|
CREATE TABLE import_polygon_delete (
|
||||||
osm_type char(1),
|
osm_id BIGINT,
|
||||||
osm_id INTEGER,
|
osm_type CHAR(1),
|
||||||
class TEXT NOT NULL,
|
class TEXT NOT NULL,
|
||||||
type TEXT NOT NULL
|
type TEXT NOT NULL
|
||||||
);
|
);
|
||||||
CREATE INDEX idx_import_polygon_delete_osmid ON import_polygon_delete USING BTREE (osm_type, osm_id);
|
CREATE INDEX idx_import_polygon_delete_osmid ON import_polygon_delete USING BTREE (osm_type, osm_id);
|
||||||
GRANT SELECT ON import_polygon_delete TO "{www-user}";
|
GRANT SELECT ON import_polygon_delete TO "{www-user}";
|
||||||
|
|
||||||
drop sequence file;
|
DROP SEQUENCE IF EXISTS file;
|
||||||
CREATE SEQUENCE file start 1;
|
CREATE SEQUENCE file start 1;
|
||||||
|
|
||||||
-- null table so it won't error
|
-- null table so it won't error
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
CREATE INDEX idx_location_property_tiger_housenumber_parent_place_id_imp ON location_property_tiger_import (parent_place_id, housenumber) {ts:aux-index};
|
--index only on parent_place_id
|
||||||
|
CREATE INDEX idx_location_property_tiger_parent_place_id_imp ON location_property_tiger_import (parent_place_id) {ts:aux-index};
|
||||||
CREATE UNIQUE INDEX idx_location_property_tiger_place_id_imp ON location_property_tiger_import (place_id) {ts:aux-index};
|
CREATE UNIQUE INDEX idx_location_property_tiger_place_id_imp ON location_property_tiger_import (place_id) {ts:aux-index};
|
||||||
|
|
||||||
GRANT SELECT ON location_property_tiger_import TO "{www-user}";
|
GRANT SELECT ON location_property_tiger_import TO "{www-user}";
|
||||||
@@ -6,7 +7,7 @@ GRANT SELECT ON location_property_tiger_import TO "{www-user}";
|
|||||||
DROP TABLE IF EXISTS location_property_tiger;
|
DROP TABLE IF EXISTS location_property_tiger;
|
||||||
ALTER TABLE location_property_tiger_import RENAME TO location_property_tiger;
|
ALTER TABLE location_property_tiger_import RENAME TO location_property_tiger;
|
||||||
|
|
||||||
ALTER INDEX idx_location_property_tiger_housenumber_parent_place_id_imp RENAME TO idx_location_property_tiger_housenumber_parent_place_id;
|
ALTER INDEX idx_location_property_tiger_parent_place_id_imp RENAME TO idx_location_property_tiger_housenumber_parent_place_id;
|
||||||
ALTER INDEX idx_location_property_tiger_place_id_imp RENAME TO idx_location_property_tiger_place_id;
|
ALTER INDEX idx_location_property_tiger_place_id_imp RENAME TO idx_location_property_tiger_place_id;
|
||||||
|
|
||||||
DROP FUNCTION tigger_create_interpolation (linegeo geometry, in_startnumber integer, in_endnumber integer, interpolationtype text, in_street text, in_isin text, in_postcode text);
|
DROP FUNCTION tiger_line_import (linegeo geometry, in_startnumber integer, in_endnumber integer, interpolationtype text, in_street text, in_isin text, in_postcode text);
|
||||||
|
|||||||
@@ -1,19 +1,15 @@
|
|||||||
DROP TABLE IF EXISTS location_property_tiger_import;
|
DROP TABLE IF EXISTS location_property_tiger_import;
|
||||||
CREATE TABLE location_property_tiger_import () INHERITS (location_property) {ts:aux-data};
|
CREATE TABLE location_property_tiger_import (linegeo GEOMETRY, place_id BIGINT, partition INTEGER, parent_place_id BIGINT, startnumber INTEGER, endnumber INTEGER, interpolationtype TEXT, postcode TEXT);
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION tigger_create_interpolation(linegeo GEOMETRY, in_startnumber INTEGER,
|
CREATE OR REPLACE FUNCTION tiger_line_import(linegeo GEOMETRY, in_startnumber INTEGER,
|
||||||
in_endnumber INTEGER, interpolationtype TEXT,
|
in_endnumber INTEGER, interpolationtype TEXT,
|
||||||
in_street TEXT, in_isin TEXT, in_postcode TEXT) RETURNS INTEGER
|
in_street TEXT, in_isin TEXT, in_postcode TEXT) RETURNS INTEGER
|
||||||
AS $$
|
AS $$
|
||||||
DECLARE
|
DECLARE
|
||||||
|
|
||||||
startnumber INTEGER;
|
startnumber INTEGER;
|
||||||
endnumber INTEGER;
|
endnumber INTEGER;
|
||||||
stepsize INTEGER;
|
stepsize INTEGER;
|
||||||
housenum INTEGER;
|
|
||||||
newpoints INTEGER;
|
|
||||||
numberrange INTEGER;
|
numberrange INTEGER;
|
||||||
rangestartnumber INTEGER;
|
|
||||||
place_centroid GEOMETRY;
|
place_centroid GEOMETRY;
|
||||||
out_partition INTEGER;
|
out_partition INTEGER;
|
||||||
out_parent_place_id BIGINT;
|
out_parent_place_id BIGINT;
|
||||||
@@ -31,7 +27,6 @@ BEGIN
|
|||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
numberrange := endnumber - startnumber;
|
numberrange := endnumber - startnumber;
|
||||||
rangestartnumber := startnumber;
|
|
||||||
|
|
||||||
IF (interpolationtype = 'odd' AND startnumber%2 = 0) OR (interpolationtype = 'even' AND startnumber%2 = 1) THEN
|
IF (interpolationtype = 'odd' AND startnumber%2 = 0) OR (interpolationtype = 'even' AND startnumber%2 = 1) THEN
|
||||||
startnumber := startnumber + 1;
|
startnumber := startnumber + 1;
|
||||||
@@ -75,15 +70,11 @@ BEGIN
|
|||||||
END LOOP;
|
END LOOP;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
newpoints := 0;
|
--insert street(line) into import table
|
||||||
FOR housenum IN startnumber..endnumber BY stepsize LOOP
|
insert into location_property_tiger_import (linegeo, place_id, partition, parent_place_id, startnumber, endnumber, interpolationtype, postcode)
|
||||||
insert into location_property_tiger_import (place_id, partition, parent_place_id, housenumber, postcode, centroid)
|
values (linegeo, nextval('seq_place'), out_partition, out_parent_place_id, startnumber, endnumber, interpolationtype, in_postcode);
|
||||||
values (nextval('seq_place'), out_partition, out_parent_place_id, housenum, in_postcode,
|
|
||||||
ST_LineInterpolatePoint(linegeo, (housenum::float-rangestartnumber::float)/numberrange::float));
|
|
||||||
newpoints := newpoints + 1;
|
|
||||||
END LOOP;
|
|
||||||
|
|
||||||
RETURN newpoints;
|
RETURN 1;
|
||||||
END;
|
END;
|
||||||
$$
|
$$
|
||||||
LANGUAGE plpgsql;
|
LANGUAGE plpgsql;
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
\a
|
|
||||||
\t
|
|
||||||
\o /tmp/bigintupdate.sql
|
|
||||||
select 'alter table "'||relname||'" alter '||attname||' type bigint;' from pg_attribute join pg_class on
|
|
||||||
(attrelid = oid) where attname like '%place_id%' and attnum > 0 and relkind = 'r'::"char" and atttypid = 23
|
|
||||||
and not relname::text ~ '^.*_[0-9]+$' order by 'alter table "'||relname||'" alter '||attname||' type
|
|
||||||
bigint;';
|
|
||||||
\o
|
|
||||||
\i /tmp/bigintupdate.sql
|
|
||||||
@@ -4,8 +4,8 @@ CREATE TABLE word_frequencies AS
|
|||||||
WHERE v is not null
|
WHERE v is not null
|
||||||
GROUP BY id);
|
GROUP BY id);
|
||||||
|
|
||||||
select count(make_keywords(v)) from (select distinct postcode as v from place) as w where v is not null;
|
select count(make_keywords(v)) from (select distinct address->'postcode' as v from place where address ? 'postcode') as w where v is not null;
|
||||||
select count(getorcreate_housenumber_id(make_standard_name(v))) from (select distinct housenumber as v from place where housenumber is not null) as w;
|
select count(getorcreate_housenumber_id(make_standard_name(v))) from (select distinct address->'housenumber' as v from place where address ? 'housenumber') as w;
|
||||||
|
|
||||||
-- copy the word frequencies
|
-- copy the word frequencies
|
||||||
update word set search_name_count = count from word_frequencies wf where wf.id = word.word_id;
|
update word set search_name_count = count from word_frequencies wf where wf.id = word.word_id;
|
||||||
|
|||||||
138
test/README.md
Normal file
138
test/README.md
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
This directory contains functional and unit tests for the Nominatim API.
|
||||||
|
|
||||||
|
Prerequisites
|
||||||
|
=============
|
||||||
|
|
||||||
|
* Python 3 (https://www.python.org/)
|
||||||
|
* behave test framework >= 1.2.5 (https://github.com/behave/behave)
|
||||||
|
* nose (https://nose.readthedocs.org)
|
||||||
|
* pytidylib (http://countergram.com/open-source/pytidylib)
|
||||||
|
* psycopg2 (http://initd.org/psycopg/)
|
||||||
|
|
||||||
|
To get the prerequisites on a a fresh Ubuntu LTS 16.04 run:
|
||||||
|
|
||||||
|
[sudo] apt-get install python3-dev python3-pip python3-psycopg2 python3-tidylib phpunit php-cgi
|
||||||
|
pip3 install --user behave nose
|
||||||
|
|
||||||
|
|
||||||
|
Overall structure
|
||||||
|
=================
|
||||||
|
|
||||||
|
There are two kind of tests in this test suite. There are functional tests
|
||||||
|
which test the API interface using a BDD test framework and there are unit
|
||||||
|
tests for specific PHP functions.
|
||||||
|
|
||||||
|
This test directory is sturctured as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
-+- bdd Functional API tests
|
||||||
|
| \
|
||||||
|
| +- steps Step implementations for test descriptions
|
||||||
|
| +- osm2pgsql Tests for data import via osm2pgsql
|
||||||
|
| +- db Tests for internal data processing on import and update
|
||||||
|
| +- api Tests for API endpoints (search, reverse, etc.)
|
||||||
|
|
|
||||||
|
+- php PHP unit tests
|
||||||
|
+- scenes Geometry test data
|
||||||
|
+- testdb Base data for generating API test database
|
||||||
|
```
|
||||||
|
|
||||||
|
PHP Unit Tests
|
||||||
|
==============
|
||||||
|
|
||||||
|
Unit tests can be found in the php/ directory and tests selected php functions.
|
||||||
|
Very low coverage.
|
||||||
|
|
||||||
|
To execute the test suite run
|
||||||
|
|
||||||
|
cd test/php
|
||||||
|
phpunit ../
|
||||||
|
|
||||||
|
It will read phpunit.xml which points to the library, test path, bootstrap
|
||||||
|
strip and set other parameters.
|
||||||
|
|
||||||
|
|
||||||
|
BDD Functional Tests
|
||||||
|
====================
|
||||||
|
|
||||||
|
Functional tests are written as BDD instructions. For more information on
|
||||||
|
the philosophy of BDD testing, see http://pythonhosted.org/behave/philosophy.html
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
To run the functional tests, do
|
||||||
|
|
||||||
|
cd test/bdd
|
||||||
|
behave
|
||||||
|
|
||||||
|
The tests can be configured with a set of environment variables:
|
||||||
|
|
||||||
|
* `BUILD_DIR` - build directory of Nominatim installation to test
|
||||||
|
* `TEMPLATE_DB` - name of template database used as a skeleton for
|
||||||
|
the test databases (db tests)
|
||||||
|
* `TEST_DB` - name of test database (db tests)
|
||||||
|
* `ABI_TEST_DB` - name of the database containing the API test data (api tests)
|
||||||
|
* `TEST_SETTINGS_TEMPLATE` - file to write temporary Nominatim settings to
|
||||||
|
* `REMOVE_TEMPLATE` - if true, the template database will not be reused during
|
||||||
|
the next run. Reusing the base templates speeds up tests
|
||||||
|
considerably but might lead to outdated errors for some
|
||||||
|
changes in the database layout.
|
||||||
|
* `KEEP_TEST_DB` - if true, the test database will not be dropped after a test
|
||||||
|
is finished. Should only be used if one single scenario is
|
||||||
|
run, otherwise the result is undefined.
|
||||||
|
|
||||||
|
Logging can be defined through command line parameters of behave itself. Check
|
||||||
|
out `behave --help` for details. Also keep an eye out for the 'work-in-progress'
|
||||||
|
feature of behave which comes in handy when writing new tests.
|
||||||
|
|
||||||
|
Writing Tests
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The following explanation assume that the reader is familiar with the BDD
|
||||||
|
notations of features, scenarios and steps.
|
||||||
|
|
||||||
|
All possible steps can be found in the `steps` directory and should ideally
|
||||||
|
be documented.
|
||||||
|
|
||||||
|
### API Tests (`test/bdd/api`)
|
||||||
|
|
||||||
|
These tests are meant to test the different API endpoints and their parameters.
|
||||||
|
They require a preimported test database, which consists of the import of a
|
||||||
|
planet extract. A precompiled PBF with the necessary data can be downloaded from
|
||||||
|
http://www.nominatim.org/data/test/nominatim-api-testdata.pbf
|
||||||
|
|
||||||
|
The polygons defining the extract can be found in the test/testdb
|
||||||
|
directory. There is also a reduced set of wikipedia data for this extract,
|
||||||
|
which you need to import as well. For Tiger tests the data of South Dakota
|
||||||
|
is required. Get the Tiger files `46*`.
|
||||||
|
|
||||||
|
The official test dataset is derived from the 160725 planet. Newer
|
||||||
|
planets are likely to work as well but you may see isolated test
|
||||||
|
failures where the data has changed. To recreate the input data
|
||||||
|
for the test database run:
|
||||||
|
|
||||||
|
wget http://free.nchc.org.tw/osm.planet/pbf/planet-160725.osm.pbf
|
||||||
|
osmconvert planet-160725.osm.pbf -B=test/testdb/testdb.polys -o=testdb.pbf
|
||||||
|
|
||||||
|
Before importing make sure to add the following to your local settings:
|
||||||
|
|
||||||
|
@define('CONST_Database_DSN', 'pgsql://@/test_api_nominatim');
|
||||||
|
@define('CONST_Wikipedia_Data_Path', CONST_BasePath.'/test/testdb');
|
||||||
|
|
||||||
|
### Indexing Tests (`test/bdd/db`)
|
||||||
|
|
||||||
|
These tests check the import and update of the Nominatim database. They do not
|
||||||
|
test the correctness of osm2pgsql. Each test will write some data into the `place`
|
||||||
|
table (and optionally `the planet_osm_*` tables if required) and then run
|
||||||
|
Nominatim's processing functions on that.
|
||||||
|
|
||||||
|
These tests need to create their own test databases. By default they will be
|
||||||
|
called `test_template_nominatim` and `test_nominatim`. Names can be changed with
|
||||||
|
the environment variables `TEMPLATE_DB` and `TEST_DB`. The user running the tests
|
||||||
|
needs superuser rights for postgres.
|
||||||
|
|
||||||
|
### Import Tests (`test/bdd/osm2pgsql`)
|
||||||
|
|
||||||
|
These tests check that data is imported correctly into the place table. They
|
||||||
|
use the same template database as the Indexing tests, so the same remarks apply.
|
||||||
3
test/bdd/.behaverc
Normal file
3
test/bdd/.behaverc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[behave]
|
||||||
|
show_skipped=False
|
||||||
|
tags=~@Fail
|
||||||
14
test/bdd/api/details/simple.feature
Normal file
14
test/bdd/api/details/simple.feature
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
@APIDB
|
||||||
|
Feature: Object details
|
||||||
|
Check details page for correctness
|
||||||
|
|
||||||
|
Scenario Outline: Details via OSM id
|
||||||
|
When sending details query for <object>
|
||||||
|
Then the result is valid html
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| object |
|
||||||
|
| 492887 |
|
||||||
|
| N4267356889 |
|
||||||
|
| W230804120 |
|
||||||
|
| R123924 |
|
||||||
17
test/bdd/api/lookup/simple.feature
Normal file
17
test/bdd/api/lookup/simple.feature
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@APIDB
|
||||||
|
Feature: Places by osm_type and osm_id Tests
|
||||||
|
Simple tests for internal server errors and response format.
|
||||||
|
|
||||||
|
Scenario Outline: address lookup for existing node, way, relation
|
||||||
|
When sending <format> lookup query for N3284625766,W6065798,,R123924,X99,N0
|
||||||
|
Then the result is valid <format>
|
||||||
|
And exactly 3 results are returned
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| xml |
|
||||||
|
| json |
|
||||||
|
|
||||||
|
Scenario: address lookup for non-existing or invalid node, way, relation
|
||||||
|
When sending xml lookup query for X99,,N0,nN158845944,ABC,,W9
|
||||||
|
Then exactly 0 results are returned
|
||||||
36
test/bdd/api/reverse/language.feature
Normal file
36
test/bdd/api/reverse/language.feature
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
@APIDB
|
||||||
|
Feature: Localization of reverse search results
|
||||||
|
|
||||||
|
Scenario: default language
|
||||||
|
When sending json reverse coordinates 18.1147,-15.95
|
||||||
|
Then result addresses contain
|
||||||
|
| ID | country |
|
||||||
|
| 0 | Mauritanie موريتانيا |
|
||||||
|
|
||||||
|
Scenario: accept-language parameter
|
||||||
|
When sending json reverse coordinates 18.1147,-15.95
|
||||||
|
| accept-language |
|
||||||
|
| en,fr |
|
||||||
|
Then result addresses contain
|
||||||
|
| ID | country |
|
||||||
|
| 0 | Mauritania |
|
||||||
|
|
||||||
|
Scenario: HTTP accept language header
|
||||||
|
Given the HTTP header
|
||||||
|
| accept-language |
|
||||||
|
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3 |
|
||||||
|
When sending json reverse coordinates 18.1147,-15.95
|
||||||
|
Then result addresses contain
|
||||||
|
| ID | country |
|
||||||
|
| 0 | Mauritanie |
|
||||||
|
|
||||||
|
Scenario: accept-language parameter and HTTP header
|
||||||
|
Given the HTTP header
|
||||||
|
| accept-language |
|
||||||
|
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3 |
|
||||||
|
When sending json reverse coordinates 18.1147,-15.95
|
||||||
|
| accept-language |
|
||||||
|
| en |
|
||||||
|
Then result addresses contain
|
||||||
|
| ID | country |
|
||||||
|
| 0 | Mauritania |
|
||||||
102
test/bdd/api/reverse/params.feature
Normal file
102
test/bdd/api/reverse/params.feature
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
@APIDB
|
||||||
|
Feature: Parameters for Reverse API
|
||||||
|
Testing different parameter options for reverse API.
|
||||||
|
|
||||||
|
Scenario Outline: Reverse-geocoding without address
|
||||||
|
When sending <format> reverse coordinates 53.603,10.041
|
||||||
|
| addressdetails |
|
||||||
|
| 0 |
|
||||||
|
Then exactly 1 result is returned
|
||||||
|
And result has not attributes address
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| json |
|
||||||
|
| jsonv2 |
|
||||||
|
| xml |
|
||||||
|
|
||||||
|
Scenario Outline: Reverse Geocoding with extratags
|
||||||
|
When sending <format> reverse coordinates 10.776234290950017,106.70425325632095
|
||||||
|
| extratags |
|
||||||
|
| 1 |
|
||||||
|
Then result 0 has attributes extratags
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| xml |
|
||||||
|
| json |
|
||||||
|
| jsonv2 |
|
||||||
|
|
||||||
|
Scenario Outline: Reverse Geocoding with namedetails
|
||||||
|
When sending <format> reverse coordinates 10.776455623137625,106.70175343751907
|
||||||
|
| namedetails |
|
||||||
|
| 1 |
|
||||||
|
Then result 0 has attributes namedetails
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| xml |
|
||||||
|
| json |
|
||||||
|
| jsonv2 |
|
||||||
|
|
||||||
|
Scenario Outline: Reverse Geocoding contains TEXT geometry
|
||||||
|
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
|
||||||
|
| polygon_text |
|
||||||
|
| 1 |
|
||||||
|
Then result 0 has attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | geotext |
|
||||||
|
| json | geotext |
|
||||||
|
| jsonv2 | geotext |
|
||||||
|
|
||||||
|
Scenario Outline: Reverse Geocoding contains polygon-as-points geometry
|
||||||
|
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
|
||||||
|
| polygon |
|
||||||
|
| 1 |
|
||||||
|
Then result 0 has not attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | polygonpoints |
|
||||||
|
| json | polygonpoints |
|
||||||
|
| jsonv2 | polygonpoints |
|
||||||
|
|
||||||
|
Scenario Outline: Reverse Geocoding contains SVG geometry
|
||||||
|
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
|
||||||
|
| polygon_svg |
|
||||||
|
| 1 |
|
||||||
|
Then result 0 has attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | geosvg |
|
||||||
|
| json | svg |
|
||||||
|
| jsonv2 | svg |
|
||||||
|
|
||||||
|
Scenario Outline: Reverse Geocoding contains KML geometry
|
||||||
|
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
|
||||||
|
| polygon_kml |
|
||||||
|
| 1 |
|
||||||
|
Then result 0 has attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | geokml |
|
||||||
|
| json | geokml |
|
||||||
|
| jsonv2 | geokml |
|
||||||
|
|
||||||
|
Scenario Outline: Reverse Geocoding contains GEOJSON geometry
|
||||||
|
When sending <format> reverse coordinates 47.165989816710066,9.515774846076965
|
||||||
|
| polygon_geojson |
|
||||||
|
| 1 |
|
||||||
|
Then result 0 has attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | geojson |
|
||||||
|
| json | geojson |
|
||||||
|
| jsonv2 | geojson |
|
||||||
|
|
||||||
|
|
||||||
25
test/bdd/api/reverse/queries.feature
Normal file
25
test/bdd/api/reverse/queries.feature
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
@APIDB
|
||||||
|
Feature: Reverse geocoding
|
||||||
|
Testing the reverse function
|
||||||
|
|
||||||
|
@Tiger
|
||||||
|
Scenario: TIGER house number
|
||||||
|
When sending jsonv2 reverse coordinates 45.3345,-97.5214
|
||||||
|
Then results contain
|
||||||
|
| osm_type | category | type |
|
||||||
|
| way | place | house |
|
||||||
|
And result addresses contain
|
||||||
|
| house_number | road | postcode | country_code |
|
||||||
|
| 906 | West 1st Street | 57274 | us |
|
||||||
|
|
||||||
|
@Tiger
|
||||||
|
Scenario: No TIGER house number for zoom < 18
|
||||||
|
When sending jsonv2 reverse coordinates 45.3345,-97.5214
|
||||||
|
| zoom |
|
||||||
|
| 17 |
|
||||||
|
Then results contain
|
||||||
|
| osm_type | category |
|
||||||
|
| way | highway |
|
||||||
|
And result addresses contain
|
||||||
|
| road | postcode | country_code |
|
||||||
|
| West 1st Street | 57274 | us |
|
||||||
129
test/bdd/api/reverse/simple.feature
Normal file
129
test/bdd/api/reverse/simple.feature
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
@APIDB
|
||||||
|
Feature: Simple Reverse Tests
|
||||||
|
Simple tests for internal server errors and response format.
|
||||||
|
|
||||||
|
Scenario Outline: Simple reverse-geocoding
|
||||||
|
When sending reverse coordinates <lat>,<lon>
|
||||||
|
Then the result is valid xml
|
||||||
|
When sending xml reverse coordinates <lat>,<lon>
|
||||||
|
Then the result is valid xml
|
||||||
|
When sending json reverse coordinates <lat>,<lon>
|
||||||
|
Then the result is valid json
|
||||||
|
When sending jsonv2 reverse coordinates <lat>,<lon>
|
||||||
|
Then the result is valid json
|
||||||
|
When sending html reverse coordinates <lat>,<lon>
|
||||||
|
Then the result is valid html
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| lat | lon |
|
||||||
|
| 0.0 | 0.0 |
|
||||||
|
| -34.830 | -56.105 |
|
||||||
|
| 45.174 | -103.072 |
|
||||||
|
| 21.156 | -12.2744 |
|
||||||
|
|
||||||
|
Scenario Outline: Testing different parameters
|
||||||
|
When sending reverse coordinates 53.603,10.041
|
||||||
|
| param | value |
|
||||||
|
| <parameter> | <value> |
|
||||||
|
Then the result is valid xml
|
||||||
|
When sending html reverse coordinates 53.603,10.041
|
||||||
|
| param | value |
|
||||||
|
| <parameter> | <value> |
|
||||||
|
Then the result is valid html
|
||||||
|
When sending xml reverse coordinates 53.603,10.041
|
||||||
|
| param | value |
|
||||||
|
| <parameter> | <value> |
|
||||||
|
Then the result is valid xml
|
||||||
|
When sending json reverse coordinates 53.603,10.041
|
||||||
|
| param | value |
|
||||||
|
| <parameter> | <value> |
|
||||||
|
Then the result is valid json
|
||||||
|
When sending jsonv2 reverse coordinates 53.603,10.041
|
||||||
|
| param | value |
|
||||||
|
| <parameter> | <value> |
|
||||||
|
Then the result is valid json
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| parameter | value |
|
||||||
|
| polygon | 1 |
|
||||||
|
| polygon | 0 |
|
||||||
|
| polygon_text | 1 |
|
||||||
|
| polygon_text | 0 |
|
||||||
|
| polygon_kml | 1 |
|
||||||
|
| polygon_kml | 0 |
|
||||||
|
| polygon_geojson | 1 |
|
||||||
|
| polygon_geojson | 0 |
|
||||||
|
| polygon_svg | 1 |
|
||||||
|
| polygon_svg | 0 |
|
||||||
|
|
||||||
|
Scenario Outline: Wrapping of legal jsonp requests
|
||||||
|
When sending <format> reverse coordinates 67.3245,0.456
|
||||||
|
| json_callback |
|
||||||
|
| foo |
|
||||||
|
Then the result is valid json
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| json |
|
||||||
|
| jsonv2 |
|
||||||
|
|
||||||
|
Scenario Outline: Boundingbox is returned
|
||||||
|
When sending <format> reverse coordinates 14.62,108.1
|
||||||
|
| zoom |
|
||||||
|
| 4 |
|
||||||
|
Then result has bounding box in 9,20,102,113
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| json |
|
||||||
|
| jsonv2 |
|
||||||
|
| xml |
|
||||||
|
|
||||||
|
Scenario Outline: Reverse-geocoding with zoom
|
||||||
|
When sending <format> reverse coordinates 53.603,10.041
|
||||||
|
| zoom |
|
||||||
|
| 10 |
|
||||||
|
Then exactly 1 result is returned
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| json |
|
||||||
|
| jsonv2 |
|
||||||
|
| html |
|
||||||
|
| xml |
|
||||||
|
|
||||||
|
Scenario: Missing lon parameter
|
||||||
|
When sending reverse coordinates 52.52,
|
||||||
|
Then a HTTP 400 is returned
|
||||||
|
|
||||||
|
Scenario: Missing lat parameter
|
||||||
|
When sending reverse coordinates ,52.52
|
||||||
|
Then a HTTP 400 is returned
|
||||||
|
|
||||||
|
Scenario: Missing osm_id parameter
|
||||||
|
When sending reverse coordinates ,
|
||||||
|
| osm_type |
|
||||||
|
| N |
|
||||||
|
Then a HTTP 400 is returned
|
||||||
|
|
||||||
|
Scenario: Missing osm_type parameter
|
||||||
|
When sending reverse coordinates ,
|
||||||
|
| osm_id |
|
||||||
|
| 3498564 |
|
||||||
|
Then a HTTP 400 is returned
|
||||||
|
|
||||||
|
Scenario Outline: Bad format for lat or lon
|
||||||
|
When sending reverse coordinates ,
|
||||||
|
| lat | lon |
|
||||||
|
| <lat> | <lon> |
|
||||||
|
Then a HTTP 400 is returned
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| lat | lon |
|
||||||
|
| 48.9660 | 8,4482 |
|
||||||
|
| 48,9660 | 8.4482 |
|
||||||
|
| 48,9660 | 8,4482 |
|
||||||
|
| 48.966.0 | 8.4482 |
|
||||||
|
| 48.966 | 8.448.2 |
|
||||||
|
| Nan | 8.448 |
|
||||||
|
| 48.966 | Nan |
|
||||||
62
test/bdd/api/search/language.feature
Normal file
62
test/bdd/api/search/language.feature
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
@APIDB
|
||||||
|
Feature: Localization of search results
|
||||||
|
|
||||||
|
Scenario: default language
|
||||||
|
When sending json search query "Vietnam"
|
||||||
|
Then results contain
|
||||||
|
| ID | display_name |
|
||||||
|
| 0 | Việt Nam |
|
||||||
|
|
||||||
|
Scenario: accept-language first
|
||||||
|
When sending json search query "Mauretanien"
|
||||||
|
| accept-language |
|
||||||
|
| en,de |
|
||||||
|
Then results contain
|
||||||
|
| ID | display_name |
|
||||||
|
| 0 | Mauritania |
|
||||||
|
|
||||||
|
Scenario: accept-language missing
|
||||||
|
When sending json search query "Mauretanien"
|
||||||
|
| accept-language |
|
||||||
|
| xx,fr,en,de |
|
||||||
|
Then results contain
|
||||||
|
| ID | display_name |
|
||||||
|
| 0 | Mauritanie |
|
||||||
|
|
||||||
|
Scenario: http accept language header first
|
||||||
|
Given the HTTP header
|
||||||
|
| accept-language |
|
||||||
|
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3 |
|
||||||
|
When sending json search query "Mauretanien"
|
||||||
|
Then results contain
|
||||||
|
| ID | display_name |
|
||||||
|
| 0 | Mauritanie |
|
||||||
|
|
||||||
|
Scenario: http accept language header and accept-language
|
||||||
|
Given the HTTP header
|
||||||
|
| accept-language |
|
||||||
|
| fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3 |
|
||||||
|
When sending json search query "Mauretanien"
|
||||||
|
| accept-language |
|
||||||
|
| de,en |
|
||||||
|
Then results contain
|
||||||
|
| ID | display_name |
|
||||||
|
| 0 | Mauretanien |
|
||||||
|
|
||||||
|
Scenario: http accept language header fallback
|
||||||
|
Given the HTTP header
|
||||||
|
| accept-language |
|
||||||
|
| fr-ca,en-ca;q=0.5 |
|
||||||
|
When sending json search query "Mauretanien"
|
||||||
|
Then results contain
|
||||||
|
| ID | display_name |
|
||||||
|
| 0 | Mauritanie |
|
||||||
|
|
||||||
|
Scenario: http accept language header fallback (upper case)
|
||||||
|
Given the HTTP header
|
||||||
|
| accept-language |
|
||||||
|
| fr-FR;q=0.8,en-ca;q=0.5 |
|
||||||
|
When sending json search query "Mauretanie"
|
||||||
|
Then results contain
|
||||||
|
| ID | display_name |
|
||||||
|
| 0 | Mauritanie |
|
||||||
300
test/bdd/api/search/params.feature
Normal file
300
test/bdd/api/search/params.feature
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
@APIDB
|
||||||
|
Feature: Search queries
|
||||||
|
Testing different queries and parameters
|
||||||
|
|
||||||
|
Scenario: Simple XML search
|
||||||
|
When sending xml search query "Schaan"
|
||||||
|
Then result 0 has attributes place_id,osm_type,osm_id
|
||||||
|
And result 0 has attributes place_rank,boundingbox
|
||||||
|
And result 0 has attributes lat,lon,display_name
|
||||||
|
And result 0 has attributes class,type,importance,icon
|
||||||
|
And result 0 has not attributes address
|
||||||
|
And result 0 has bounding box in 46.5,47.5,9,10
|
||||||
|
|
||||||
|
Scenario: Simple JSON search
|
||||||
|
When sending json search query "Vaduz"
|
||||||
|
Then result 0 has attributes place_id,licence,icon,class,type
|
||||||
|
And result 0 has attributes osm_type,osm_id,boundingbox
|
||||||
|
And result 0 has attributes lat,lon,display_name,importance
|
||||||
|
And result 0 has not attributes address
|
||||||
|
And result 0 has bounding box in 46.5,47.5,9,10
|
||||||
|
|
||||||
|
Scenario: JSON search with addressdetails
|
||||||
|
When sending json search query "Montevideo" with address
|
||||||
|
Then address of result 0 is
|
||||||
|
| type | value |
|
||||||
|
| city | Montevideo |
|
||||||
|
| state | Montevideo |
|
||||||
|
| country | Uruguay |
|
||||||
|
| country_code | uy |
|
||||||
|
|
||||||
|
Scenario: XML search with addressdetails
|
||||||
|
When sending xml search query "Aleg" with address
|
||||||
|
| accept-language |
|
||||||
|
| en |
|
||||||
|
Then address of result 0 is
|
||||||
|
| type | value |
|
||||||
|
| city | Aleg |
|
||||||
|
| state | Brakna |
|
||||||
|
| country | Mauritania |
|
||||||
|
| country_code | mr |
|
||||||
|
|
||||||
|
Scenario: coordinate search with addressdetails
|
||||||
|
When sending json search query "14.271104294939,107.69828796387"
|
||||||
|
| accept-language |
|
||||||
|
| en |
|
||||||
|
Then results contain
|
||||||
|
| display_name |
|
||||||
|
| Plei Ya Rê, Kon Tum province, Vietnam |
|
||||||
|
|
||||||
|
Scenario: Address details with unknown class types
|
||||||
|
When sending json search query "Hundeauslauf, Hamburg" with address
|
||||||
|
Then results contain
|
||||||
|
| ID | class | type |
|
||||||
|
| 0 | leisure | dog_park |
|
||||||
|
And result addresses contain
|
||||||
|
| ID | address29 |
|
||||||
|
| 0 | Hundeauslauf |
|
||||||
|
And address of result 0 has no types leisure,dog_park
|
||||||
|
|
||||||
|
Scenario: Disabling deduplication
|
||||||
|
When sending json search query "Sievekingsallee, Hamburg"
|
||||||
|
Then there are no duplicates
|
||||||
|
When sending json search query "Sievekingsallee, Hamburg"
|
||||||
|
| dedupe |
|
||||||
|
| 0 |
|
||||||
|
Then there are duplicates
|
||||||
|
|
||||||
|
Scenario: Search with bounded viewbox in right area
|
||||||
|
When sending json search query "restaurant" with address
|
||||||
|
| bounded | viewbox |
|
||||||
|
| 1 | -56.16786,-34.84061,-56.12525,-34.86526 |
|
||||||
|
Then result addresses contain
|
||||||
|
| city |
|
||||||
|
| Montevideo |
|
||||||
|
|
||||||
|
Scenario: Search with bounded viewboxlbrt in right area
|
||||||
|
When sending json search query "restaurant" with address
|
||||||
|
| bounded | viewboxlbrt |
|
||||||
|
| 1 | -56.16786,-34.86526,-56.12525,-34.84061 |
|
||||||
|
Then result addresses contain
|
||||||
|
| city |
|
||||||
|
| Montevideo |
|
||||||
|
|
||||||
|
Scenario: No POI search with unbounded viewbox
|
||||||
|
When sending json search query "restaurant"
|
||||||
|
| viewbox |
|
||||||
|
| 9.93027,53.61634,10.10073,53.54500 |
|
||||||
|
Then results contain
|
||||||
|
| display_name |
|
||||||
|
| ^[^,]*[Rr]estaurant.* |
|
||||||
|
|
||||||
|
Scenario: bounded search remains within viewbox, even with no results
|
||||||
|
When sending json search query "restaurant"
|
||||||
|
| bounded | viewbox |
|
||||||
|
| 1 | 43.5403125,-5.6563282,43.54285,-5.662003 |
|
||||||
|
Then less than 1 result is returned
|
||||||
|
|
||||||
|
Scenario: bounded search remains within viewbox with results
|
||||||
|
When sending json search query "restaurant"
|
||||||
|
| bounded | viewbox |
|
||||||
|
| 1 | 9.93027,53.61634,10.10073,53.54500 |
|
||||||
|
Then result has bounding box in 53.54500,53.61634,9.93027,10.10073
|
||||||
|
|
||||||
|
Scenario: Prefer results within viewbox
|
||||||
|
When sending json search query "25 de Mayo" with address
|
||||||
|
| accept-language |
|
||||||
|
| en |
|
||||||
|
Then result addresses contain
|
||||||
|
| ID | state |
|
||||||
|
| 0 | Salto |
|
||||||
|
When sending json search query "25 de Mayo" with address
|
||||||
|
| accept-language | viewbox |
|
||||||
|
| en | -56.35879,-34.18330,-56.31618,-34.20815 |
|
||||||
|
Then result addresses contain
|
||||||
|
| ID | state |
|
||||||
|
| 0 | Florida |
|
||||||
|
|
||||||
|
Scenario: Overly large limit number for search results
|
||||||
|
When sending json search query "restaurant"
|
||||||
|
| limit |
|
||||||
|
| 1000 |
|
||||||
|
Then at most 50 results are returned
|
||||||
|
|
||||||
|
Scenario: Limit number of search results
|
||||||
|
When sending json search query "restaurant"
|
||||||
|
| limit |
|
||||||
|
| 4 |
|
||||||
|
Then exactly 4 results are returned
|
||||||
|
|
||||||
|
Scenario: Restrict to feature type country
|
||||||
|
When sending xml search query "Uruguay"
|
||||||
|
Then results contain
|
||||||
|
| ID | place_rank |
|
||||||
|
| 1 | 16 |
|
||||||
|
When sending xml search query "Uruguay"
|
||||||
|
| featureType |
|
||||||
|
| country |
|
||||||
|
Then results contain
|
||||||
|
| place_rank |
|
||||||
|
| 4 |
|
||||||
|
|
||||||
|
Scenario: Restrict to feature type state
|
||||||
|
When sending xml search query "Dakota"
|
||||||
|
Then results contain
|
||||||
|
| place_rank |
|
||||||
|
| 12 |
|
||||||
|
When sending xml search query "Dakota"
|
||||||
|
| featureType |
|
||||||
|
| state |
|
||||||
|
Then results contain
|
||||||
|
| place_rank |
|
||||||
|
| 8 |
|
||||||
|
|
||||||
|
Scenario: Restrict to feature type city
|
||||||
|
When sending xml search query "vaduz"
|
||||||
|
Then results contain
|
||||||
|
| ID | place_rank |
|
||||||
|
| 1 | 30 |
|
||||||
|
When sending xml search query "vaduz"
|
||||||
|
| featureType |
|
||||||
|
| city |
|
||||||
|
Then results contain
|
||||||
|
| place_rank |
|
||||||
|
| 16 |
|
||||||
|
|
||||||
|
Scenario: Restrict to feature type settlement
|
||||||
|
When sending json search query "Burg"
|
||||||
|
Then results contain
|
||||||
|
| ID | class |
|
||||||
|
| 1 | amenity |
|
||||||
|
When sending json search query "Burg"
|
||||||
|
| featureType |
|
||||||
|
| settlement |
|
||||||
|
Then results contain
|
||||||
|
| class | type |
|
||||||
|
| boundary | administrative |
|
||||||
|
|
||||||
|
Scenario Outline: Search with polygon threshold (json)
|
||||||
|
When sending json search query "switzerland"
|
||||||
|
| polygon_geojson | polygon_threshold |
|
||||||
|
| 1 | <th> |
|
||||||
|
Then at least 1 result is returned
|
||||||
|
And result 0 has attributes geojson
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| th |
|
||||||
|
| -1 |
|
||||||
|
| 0.0 |
|
||||||
|
| 0.5 |
|
||||||
|
| 999 |
|
||||||
|
|
||||||
|
Scenario Outline: Search with polygon threshold (xml)
|
||||||
|
When sending xml search query "switzerland"
|
||||||
|
| polygon_geojson | polygon_threshold |
|
||||||
|
| 1 | <th> |
|
||||||
|
Then at least 1 result is returned
|
||||||
|
And result 0 has attributes geojson
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| th |
|
||||||
|
| -1 |
|
||||||
|
| 0.0 |
|
||||||
|
| 0.5 |
|
||||||
|
| 999 |
|
||||||
|
|
||||||
|
Scenario Outline: Search with invalid polygon threshold (xml)
|
||||||
|
When sending xml search query "switzerland"
|
||||||
|
| polygon_geojson | polygon_threshold |
|
||||||
|
| 1 | <th> |
|
||||||
|
Then a HTTP 400 is returned
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| th |
|
||||||
|
| x |
|
||||||
|
| ;; |
|
||||||
|
| 1m |
|
||||||
|
|
||||||
|
Scenario Outline: Search with extratags
|
||||||
|
When sending <format> search query "Hauptstr"
|
||||||
|
| extratags |
|
||||||
|
| 1 |
|
||||||
|
Then result has attributes extratags
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| xml |
|
||||||
|
| json |
|
||||||
|
| jsonv2 |
|
||||||
|
|
||||||
|
Scenario Outline: Search with namedetails
|
||||||
|
When sending <format> search query "Hauptstr"
|
||||||
|
| namedetails |
|
||||||
|
| 1 |
|
||||||
|
Then result has attributes namedetails
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| xml |
|
||||||
|
| json |
|
||||||
|
| jsonv2 |
|
||||||
|
|
||||||
|
Scenario Outline: Search result with contains TEXT geometry
|
||||||
|
When sending <format> search query "Highmore"
|
||||||
|
| polygon_text |
|
||||||
|
| 1 |
|
||||||
|
Then result has attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | geotext |
|
||||||
|
| json | geotext |
|
||||||
|
| jsonv2 | geotext |
|
||||||
|
|
||||||
|
Scenario Outline: Search result contains polygon-as-points geometry
|
||||||
|
When sending <format> search query "Highmore"
|
||||||
|
| polygon |
|
||||||
|
| 1 |
|
||||||
|
Then result has attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | polygonpoints |
|
||||||
|
| json | polygonpoints |
|
||||||
|
| jsonv2 | polygonpoints |
|
||||||
|
|
||||||
|
Scenario Outline: Search result contains SVG geometry
|
||||||
|
When sending <format> search query "Highmore"
|
||||||
|
| polygon_svg |
|
||||||
|
| 1 |
|
||||||
|
Then result has attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | geosvg |
|
||||||
|
| json | svg |
|
||||||
|
| jsonv2 | svg |
|
||||||
|
|
||||||
|
Scenario Outline: Search result contains KML geometry
|
||||||
|
When sending <format> search query "Highmore"
|
||||||
|
| polygon_kml |
|
||||||
|
| 1 |
|
||||||
|
Then result has attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | geokml |
|
||||||
|
| json | geokml |
|
||||||
|
| jsonv2 | geokml |
|
||||||
|
|
||||||
|
Scenario Outline: Search result contains GEOJSON geometry
|
||||||
|
When sending <format> search query "Highmore"
|
||||||
|
| polygon_geojson |
|
||||||
|
| 1 |
|
||||||
|
Then result has attributes <response_attribute>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format | response_attribute |
|
||||||
|
| xml | geojson |
|
||||||
|
| json | geojson |
|
||||||
|
| jsonv2 | geojson |
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user