mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-14 18:37:58 +00:00
Compare commits
1 Commits
v3.3.0
...
add-logend
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e7ea9662e |
@@ -11,8 +11,6 @@ git:
|
||||
env:
|
||||
- TEST_SUITE=tests
|
||||
- TEST_SUITE=monaco
|
||||
before_install:
|
||||
- phpenv global 7.1
|
||||
install:
|
||||
- vagrant/install-on-travis-ci.sh
|
||||
before_script:
|
||||
@@ -21,7 +19,7 @@ script:
|
||||
- cd $TRAVIS_BUILD_DIR/
|
||||
- if [[ $TEST_SUITE == "tests" ]]; then phpcs --report-width=120 . ; fi
|
||||
- cd $TRAVIS_BUILD_DIR/test/php
|
||||
- if [[ $TEST_SUITE == "tests" ]]; then /usr/bin/phpunit ./ ; fi
|
||||
- if [[ $TEST_SUITE == "tests" ]]; then phpunit ./ ; fi
|
||||
- cd $TRAVIS_BUILD_DIR/test/bdd
|
||||
- # behave --format=progress3 api
|
||||
- if [[ $TEST_SUITE == "tests" ]]; then behave -DREMOVE_TEMPLATE=1 --format=progress3 db ; fi
|
||||
|
||||
@@ -19,7 +19,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
project(nominatim)
|
||||
|
||||
set(NOMINATIM_VERSION_MAJOR 3)
|
||||
set(NOMINATIM_VERSION_MINOR 3)
|
||||
set(NOMINATIM_VERSION_MINOR 2)
|
||||
set(NOMINATIM_VERSION_PATCH 0)
|
||||
|
||||
set(NOMINATIM_VERSION "${NOMINATIM_VERSION_MAJOR}.${NOMINATIM_VERSION_MINOR}.${NOMINATIM_VERSION_PATCH}")
|
||||
|
||||
24
ChangeLog
24
ChangeLog
@@ -1,27 +1,3 @@
|
||||
3.3.0
|
||||
|
||||
* zoom 17 in reverse now zooms in on minor streets
|
||||
* fix use of postcode relations in address
|
||||
* support for housenumber 0 on interpolations
|
||||
* replace database abstraction DB with PDO and switch to using exceptions
|
||||
* exclude line features at rank 30 from reverse geocoding
|
||||
* remove self-reference and country from place_addressline
|
||||
* make json output more readable (less escaping)
|
||||
* update conversion scripts for postcodes
|
||||
* scripts in utils/ are no longer executable (always use scripts in build dir)
|
||||
* remove Natural Earth country fallback (OSM is complete enough)
|
||||
* make rank assignments configurable
|
||||
* allow accept languages with underscore
|
||||
* new reverse-only import mode (without search index table)
|
||||
* rely on boundaries only for states and countries
|
||||
* update osm2pgsql, now using a configurable style
|
||||
* provide multiple import styles
|
||||
* improve search when house number and postcodes are dropped
|
||||
* overhaul of setup code
|
||||
* add support for PHPUnit 6
|
||||
* update test database
|
||||
* various documentation improvements
|
||||
|
||||
3.2.0
|
||||
|
||||
* complete rewrite of reverse search algorithm
|
||||
|
||||
@@ -59,5 +59,5 @@ Both bug reports and pull requests are welcome.
|
||||
Mailing list
|
||||
============
|
||||
|
||||
For questions you can join the geocoding mailing list, see
|
||||
For questions you can join the geocoding mailinglist, see
|
||||
https://lists.openstreetmap.org/listinfo/geocoding
|
||||
|
||||
@@ -171,7 +171,7 @@ If the Postgres installation is behind a firewall, you can try
|
||||
inside the virtual machine. It will map the port to `localhost:9999` and then
|
||||
you edit `settings/local.php` with
|
||||
|
||||
@define('CONST_Database_DSN', 'pgsql:host=localhost;port=9999;user=postgres;dbname=nominatim_it');
|
||||
@define('CONST_Database_DSN', 'pgsql://postgres@localhost:9999/nominatim_it');
|
||||
|
||||
To access postgres directly remember to specify the hostname, e.g. `psql --host localhost --port 9999 nominatim_it`
|
||||
|
||||
|
||||
@@ -25,32 +25,41 @@ If you forgot to download the file, or have a new version, you can import it sep
|
||||
|
||||
2. `unzip codepo_gb.zip`
|
||||
|
||||
Unpacked you'll see a directory of CSV files.
|
||||
Unpacked you'll see a directory of CSV files.
|
||||
|
||||
$ more codepo_gb/Data/CSV/n.csv
|
||||
"N1 0AA",10,530626,183961,"E92000001","E19000003","E18000007","","E09000019","E05000368"
|
||||
"N1 0AB",10,530559,183978,"E92000001","E19000003","E18000007","","E09000019","E05000368"
|
||||
```
|
||||
$ more codepo_gb/Data/CSV/n.csv
|
||||
"N1 0AA",10,530626,183961,"E92000001","E19000003","E18000007","","E09000019","E05000368"
|
||||
"N1 0AB",10,530559,183978,"E92000001","E19000003","E18000007","","E09000019","E05000368"
|
||||
```
|
||||
|
||||
The coordinates are "Northings" and "Eastings" in [OSGB 1936](http://epsg.io/1314) projection. They can be projected to WGS84 like this
|
||||
The coordinates are "Northings" and "Eastings" in [OSGB 1936](http://epsg.io/1314) projection. They can be projected to WGS84 like this
|
||||
|
||||
SELECT ST_AsText(ST_Transform(ST_SetSRID('POINT(530626 183961)'::geometry,27700), 4326));
|
||||
POINT(-0.117872733220225 51.5394424719303)
|
||||
|
||||
[-0.117872733220225 51.5394424719303 on OSM map](https://www.openstreetmap.org/?mlon=-0.117872733220225&mlat=51.5394424719303&zoom=16)
|
||||
```
|
||||
SELECT ST_AsText(ST_Transform(ST_SetSRID('POINT(530626 183961)'::geometry,27700), 4326));
|
||||
POINT(-0.117872733220225 51.5394424719303)
|
||||
```
|
||||
[-0.117872733220225 51.5394424719303 on OSM map](https://www.openstreetmap.org/?mlon=-0.117872733220225&mlat=51.5394424719303&zoom=16)
|
||||
|
||||
|
||||
|
||||
3. Create database, import CSV files, add geometry column, dump into file
|
||||
|
||||
DBNAME=create_gb_postcode_file
|
||||
createdb $DBNAME
|
||||
echo 'CREATE EXTENSION postgis' | psql $DBNAME
|
||||
|
||||
cat data/gb_postcode_table.sql | psql $DBNAME
|
||||
cat codepo_gb/Data/CSV/*.csv | ./data-sources/gb-postcodes/convert_codepoint.php | psql $DBNAME
|
||||
cat codepo_gb/Doc/licence.txt | iconv -f iso-8859-1 -t utf-8 | dos2unix | sed 's/^/-- /g' > gb_postcode_data.sql
|
||||
pg_dump -a -t gb_postcode $DBNAME | grep -v '^--' >> gb_postcode_data.sql
|
||||
|
||||
gzip -9 -f gb_postcode_data.sql
|
||||
ls -lah gb_postcode_data.*
|
||||
# dropdb $DBNAME
|
||||
```
|
||||
DBNAME=create_gb_postcode_file
|
||||
|
||||
createdb $DBNAME
|
||||
echo 'CREATE EXTENSION postgis' | psql $DBNAME
|
||||
|
||||
cat data/gb_postcode_table.sql | psql $DBNAME
|
||||
|
||||
cat codepo_gb/Data/CSV/*.csv | ./data-sources/gb-postcodes/convert_codepoint.php | psql $DBNAME
|
||||
|
||||
cat codepo_gb/Doc/licence.txt | iconv -f iso-8859-1 -t utf-8 | dos2unix | sed 's/^/-- /g' > gb_postcode_data.sql
|
||||
pg_dump -a -t gb_postcode $DBNAME | grep -v '^--' >> gb_postcode_data.sql
|
||||
|
||||
gzip -9 -f gb_postcode_data.sql
|
||||
ls -lah gb_postcode_data.*
|
||||
|
||||
# dropdb $DBNAME
|
||||
```
|
||||
|
||||
@@ -81,14 +81,6 @@ If you are using a flatnode file, then it may also be that the underlying
|
||||
filesystem does not fully support 'mmap'. A notable candidate is virtualbox's
|
||||
vboxfs.
|
||||
|
||||
### nominatim UPDATE failed: ERROR: buffer 179261 is not owned by resource owner Portal
|
||||
|
||||
Several users [reported this](https://github.com/openstreetmap/Nominatim/issues/1168) during the initial import of the database. It's
|
||||
something Postgresql internal Nominatim doesn't control. And Postgresql forums
|
||||
suggest it's threading related but definitely some kind of crash of a process.
|
||||
Users reported either rebooting the server, different hardware or just trying
|
||||
the import again worked.
|
||||
|
||||
### The website shows: "Could not get word tokens"
|
||||
|
||||
The server cannot access your database. Add `&debug=1` to your URL
|
||||
@@ -112,8 +104,11 @@ However, you can solve this the quick and dirty way by commenting out that line
|
||||
|
||||
### "must be an array or an object that implements Countable" warning in /usr/share/pear/DB.php
|
||||
|
||||
The warning started with PHP 7.2. Make sure you have at least [version 1.9.3 of PEAR DB](https://github.com/pear/DB/releases)
|
||||
installed.
|
||||
As reported starting PHP 7.2. This external DB library is no longer maintained and will be replaced in future Nominatim versions. In the meantime you'd have to manually change the line near 774 from
|
||||
`if (!count($dsn)) {` to `if (!$dsn && !count($dsn))`. [More details](https://github.com/openstreetmap/Nominatim/issues/1184)
|
||||
|
||||
|
||||
|
||||
|
||||
### Website reports "DB Error: insufficient permissions"
|
||||
|
||||
|
||||
@@ -7,19 +7,7 @@ SQL statements should be executed from the postgres commandline. Execute
|
||||
`psql nominatim` to enter command line mode.
|
||||
|
||||
|
||||
## 3.2.0 -> 3.3.0
|
||||
|
||||
### New database connection string (DSN) format
|
||||
|
||||
Previously database connection setting (`CONST_Database_DSN` in `settings/*.php`) had the format
|
||||
|
||||
* (simple) `pgsql://@/nominatim`
|
||||
* (complex) `pgsql://johndoe:secret@machine1.domain.com:1234/db1`
|
||||
|
||||
The new format is
|
||||
|
||||
* (simple) `pgsql:dbname=nominatim`
|
||||
* (complex) `pgsql:dbname=db1;host=machine1.domain.com;port=1234;user=johndoe;password=secret`
|
||||
## 3.2.0 -> master
|
||||
|
||||
### Natural Earth country boundaries no longer needed as fallback
|
||||
|
||||
|
||||
@@ -80,8 +80,7 @@ In terms of address details the zoom levels are as follows:
|
||||
8 | county
|
||||
10 | city
|
||||
14 | suburb
|
||||
16 | major streets
|
||||
17 | major and minor streets
|
||||
16 | street
|
||||
18 | building
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class AddressDetails
|
||||
$mLangPref = 'ARRAY['.join(',', array_map('getDBQuoted', $mLangPref)).']';
|
||||
}
|
||||
|
||||
if (!isset($sHousenumber)) {
|
||||
if (!$sHousenumber) {
|
||||
$sHousenumber = -1;
|
||||
}
|
||||
|
||||
@@ -26,12 +26,12 @@ class AddressDetails
|
||||
$sSQL .= ' FROM get_addressdata('.$iPlaceID.','.$sHousenumber.')';
|
||||
$sSQL .= ' ORDER BY rank_address DESC, isaddress DESC';
|
||||
|
||||
$this->aAddressLines = $oDB->getAll($sSQL);
|
||||
$this->aAddressLines = chksql($oDB->getAll($sSQL));
|
||||
}
|
||||
|
||||
private static function isAddress($aLine)
|
||||
{
|
||||
return $aLine['isaddress'] || $aLine['type'] == 'country_code';
|
||||
return $aLine['isaddress'] == 't' || $aLine['type'] == 'country_code';
|
||||
}
|
||||
|
||||
public function getAddressDetails($bAll = false)
|
||||
@@ -49,7 +49,7 @@ class AddressDetails
|
||||
$sPrevResult = '';
|
||||
|
||||
foreach ($this->aAddressLines as $aLine) {
|
||||
if ($aLine['isaddress'] && $sPrevResult != $aLine['localname']) {
|
||||
if ($aLine['isaddress'] == 't' && $sPrevResult != $aLine['localname']) {
|
||||
$sPrevResult = $aLine['localname'];
|
||||
$aParts[] = $sPrevResult;
|
||||
}
|
||||
|
||||
298
lib/DB.php
298
lib/DB.php
@@ -1,298 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Nominatim;
|
||||
|
||||
require_once(CONST_BasePath.'/lib/DatabaseError.php');
|
||||
|
||||
/**
|
||||
* Uses PDO to access the database specified in the CONST_Database_DSN
|
||||
* setting.
|
||||
*/
|
||||
class DB
|
||||
{
|
||||
protected $connection;
|
||||
|
||||
public function __construct($sDSN = CONST_Database_DSN)
|
||||
{
|
||||
$this->sDSN = $sDSN;
|
||||
}
|
||||
|
||||
public function connect($bNew = false, $bPersistent = true)
|
||||
{
|
||||
if (isset($this->connection) && !$bNew) {
|
||||
return true;
|
||||
}
|
||||
$aConnOptions = array(
|
||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||||
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
|
||||
\PDO::ATTR_PERSISTENT => $bPersistent
|
||||
);
|
||||
|
||||
// https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
|
||||
try {
|
||||
$conn = new \PDO($this->sDSN, null, null, $aConnOptions);
|
||||
} catch (\PDOException $e) {
|
||||
$sMsg = 'Failed to establish database connection:' . $e->getMessage();
|
||||
throw new \Nominatim\DatabaseError($sMsg, 500, null, $e->getMessage());
|
||||
}
|
||||
|
||||
$conn->exec("SET DateStyle TO 'sql,european'");
|
||||
$conn->exec("SET client_encoding TO 'utf-8'");
|
||||
$iMaxExecution = ini_get('max_execution_time');
|
||||
if ($iMaxExecution > 0) $conn->setAttribute(\PDO::ATTR_TIMEOUT, $iMaxExecution); // seconds
|
||||
|
||||
$this->connection = $conn;
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns the number of rows that were modified or deleted by the SQL
|
||||
// statement. If no rows were affected returns 0.
|
||||
public function exec($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
|
||||
{
|
||||
$val = null;
|
||||
try {
|
||||
if (isset($aInputVars)) {
|
||||
$stmt = $this->connection->prepare($sSQL);
|
||||
$stmt->execute($aInputVars);
|
||||
} else {
|
||||
$val = $this->connection->exec($sSQL);
|
||||
}
|
||||
} catch (\PDOException $e) {
|
||||
throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes query. Returns first row as array.
|
||||
* Returns false if no result found.
|
||||
*
|
||||
* @param string $sSQL
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function getRow($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
|
||||
{
|
||||
try {
|
||||
$stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
|
||||
$row = $stmt->fetch();
|
||||
} catch (\PDOException $e) {
|
||||
throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes query. Returns first value of first result.
|
||||
* Returns false if no results found.
|
||||
*
|
||||
* @param string $sSQL
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function getOne($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
|
||||
{
|
||||
try {
|
||||
$stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
|
||||
$row = $stmt->fetch(\PDO::FETCH_NUM);
|
||||
if ($row === false) return false;
|
||||
} catch (\PDOException $e) {
|
||||
throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
|
||||
}
|
||||
return $row[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes query. Returns array of results (arrays).
|
||||
* Returns empty array if no results found.
|
||||
*
|
||||
* @param string $sSQL
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function getAll($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
|
||||
{
|
||||
try {
|
||||
$stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
|
||||
$rows = $stmt->fetchAll();
|
||||
} catch (\PDOException $e) {
|
||||
throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes query. Returns array of the first value of each result.
|
||||
* Returns empty array if no results found.
|
||||
*
|
||||
* @param string $sSQL
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function getCol($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
|
||||
{
|
||||
$aVals = array();
|
||||
try {
|
||||
$stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
|
||||
|
||||
while ($val = $stmt->fetchColumn(0)) { // returns first column or false
|
||||
$aVals[] = $val;
|
||||
}
|
||||
} catch (\PDOException $e) {
|
||||
throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
|
||||
}
|
||||
return $aVals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes query. Returns associate array mapping first value to second value of each result.
|
||||
* Returns empty array if no results found.
|
||||
*
|
||||
* @param string $sSQL
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function getAssoc($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
|
||||
{
|
||||
try {
|
||||
$stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
|
||||
|
||||
$aList = array();
|
||||
while ($aRow = $stmt->fetch(\PDO::FETCH_NUM)) {
|
||||
$aList[$aRow[0]] = $aRow[1];
|
||||
}
|
||||
} catch (\PDOException $e) {
|
||||
throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
|
||||
}
|
||||
return $aList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes query. Returns a PDO statement to iterate over.
|
||||
*
|
||||
* @param string $sSQL
|
||||
*
|
||||
* @return PDOStatement
|
||||
*/
|
||||
public function getQueryStatement($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
|
||||
{
|
||||
try {
|
||||
if (isset($aInputVars)) {
|
||||
$stmt = $this->connection->prepare($sSQL);
|
||||
$stmt->execute($aInputVars);
|
||||
} else {
|
||||
$stmt = $this->connection->query($sSQL);
|
||||
}
|
||||
} catch (\PDOException $e) {
|
||||
throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
|
||||
}
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* St. John's Way => 'St. John\'s Way'
|
||||
*
|
||||
* @param string $sVal Text to be quoted.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDBQuoted($sVal)
|
||||
{
|
||||
return $this->connection->quote($sVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like getDBQuoted, but takes an array.
|
||||
*
|
||||
* @param array $aVals List of text to be quoted.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function getDBQuotedList($aVals)
|
||||
{
|
||||
return array_map(function ($sVal) {
|
||||
return $this->getDBQuoted($sVal);
|
||||
}, $aVals);
|
||||
}
|
||||
|
||||
/**
|
||||
* [1,2,'b'] => 'ARRAY[1,2,'b']''
|
||||
*
|
||||
* @param array $aVals List of text to be quoted.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getArraySQL($a)
|
||||
{
|
||||
return 'ARRAY['.join(',', $a).']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a table exists in the database. Returns true if it does.
|
||||
*
|
||||
* @param string $sTableName
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function tableExists($sTableName)
|
||||
{
|
||||
$sSQL = 'SELECT count(*) FROM pg_tables WHERE tablename = :tablename';
|
||||
return ($this->getOne($sSQL, array(':tablename' => $sTableName)) == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since the DSN includes the database name, checks if the connection works.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function databaseExists()
|
||||
{
|
||||
$bExists = true;
|
||||
try {
|
||||
$this->connect(true);
|
||||
} catch (\Nominatim\DatabaseError $e) {
|
||||
$bExists = false;
|
||||
}
|
||||
return $bExists;
|
||||
}
|
||||
|
||||
/**
|
||||
* e.g. 9.6, 10, 11.2
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getPostgresVersion()
|
||||
{
|
||||
$sVersionString = $this->getOne('SHOW server_version_num');
|
||||
preg_match('#([0-9]?[0-9])([0-9][0-9])[0-9][0-9]#', $sVersionString, $aMatches);
|
||||
return (float) ($aMatches[1].'.'.$aMatches[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* e.g. 2, 2.2
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getPostgisVersion()
|
||||
{
|
||||
$sVersionString = $this->getOne('select postgis_lib_version()');
|
||||
preg_match('#^([0-9]+)[.]([0-9]+)[.]#', $sVersionString, $aMatches);
|
||||
return (float) ($aMatches[1].'.'.$aMatches[2]);
|
||||
}
|
||||
|
||||
public static function parseDSN($sDSN)
|
||||
{
|
||||
// https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
|
||||
$aInfo = array();
|
||||
if (preg_match('/^pgsql:(.+)/', $sDSN, $aMatches)) {
|
||||
foreach (explode(';', $aMatches[1]) as $sKeyVal) {
|
||||
list($sKey, $sVal) = explode('=', $sKeyVal, 2);
|
||||
if ($sKey == 'host') $sKey = 'hostspec';
|
||||
if ($sKey == 'dbname') $sKey = 'database';
|
||||
if ($sKey == 'user') $sKey = 'username';
|
||||
$aInfo[$sKey] = $sVal;
|
||||
}
|
||||
}
|
||||
return $aInfo;
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,10 @@ namespace Nominatim;
|
||||
class DatabaseError extends \Exception
|
||||
{
|
||||
|
||||
public function __construct($message, $code = 500, Exception $previous = null, $oPDOErr, $sSql = null)
|
||||
public function __construct($message, $code = 500, Exception $previous = null, $oSql)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
// https://secure.php.net/manual/en/class.pdoexception.php
|
||||
$this->oPDOErr = $oPDOErr;
|
||||
$this->sSql = $sSql;
|
||||
$this->oSql = $oSql;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
@@ -20,15 +18,15 @@ class DatabaseError extends \Exception
|
||||
|
||||
public function getSqlError()
|
||||
{
|
||||
return $this->oPDOErr->getMessage();
|
||||
return $this->oSql->getMessage();
|
||||
}
|
||||
|
||||
public function getSqlDebugDump()
|
||||
{
|
||||
if (CONST_Debug) {
|
||||
return var_export($this->oPDOErr, true);
|
||||
return var_export($this->oSql, true);
|
||||
} else {
|
||||
return $this->sSql;
|
||||
return $this->oSql->getUserInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,8 +527,8 @@ class Geocode
|
||||
$sNormQuery = $this->normTerm($this->sQuery);
|
||||
Debug::printVar('Normalized query', $sNormQuery);
|
||||
|
||||
$sLanguagePrefArraySQL = $this->oDB->getArraySQL(
|
||||
$this->oDB->getDBQuotedList($this->aLangPrefOrder)
|
||||
$sLanguagePrefArraySQL = getArraySQL(
|
||||
array_map('getDBQuoted', $this->aLangPrefOrder)
|
||||
);
|
||||
|
||||
$sQuery = $this->sQuery;
|
||||
@@ -581,9 +581,8 @@ class Geocode
|
||||
|
||||
if ($sSpecialTerm && !$aSearches[0]->hasOperator()) {
|
||||
$sSpecialTerm = pg_escape_string($sSpecialTerm);
|
||||
$sToken = $this->oDB->getOne(
|
||||
'SELECT make_standard_name(:term)',
|
||||
array(':term' => $sSpecialTerm),
|
||||
$sToken = chksql(
|
||||
$this->oDB->getOne("SELECT make_standard_name('$sSpecialTerm')"),
|
||||
'Cannot decode query. Wrong encoding?'
|
||||
);
|
||||
$sSQL = 'SELECT class, type FROM word ';
|
||||
@@ -591,7 +590,7 @@ class Geocode
|
||||
$sSQL .= ' AND class is not null AND class not in (\'place\')';
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
$aSearchWords = $this->oDB->getAll($sSQL);
|
||||
$aSearchWords = chksql($this->oDB->getAll($sSQL));
|
||||
$aNewSearches = array();
|
||||
foreach ($aSearches as $oSearch) {
|
||||
foreach ($aSearchWords as $aSearchTerm) {
|
||||
@@ -629,9 +628,8 @@ class Geocode
|
||||
$aTokens = array();
|
||||
$aPhrases = array();
|
||||
foreach ($aInPhrases as $iPhrase => $sPhrase) {
|
||||
$sPhrase = $this->oDB->getOne(
|
||||
'SELECT make_standard_name(:phrase)',
|
||||
array(':phrase' => $sPhrase),
|
||||
$sPhrase = chksql(
|
||||
$this->oDB->getOne('SELECT make_standard_name('.getDBQuoted($sPhrase).')'),
|
||||
'Cannot normalize query string (is it a UTF-8 string?)'
|
||||
);
|
||||
if (trim($sPhrase)) {
|
||||
@@ -649,7 +647,7 @@ class Geocode
|
||||
if (!empty($aTokens)) {
|
||||
$sSQL = 'SELECT word_id, word_token, word, class, type, country_code, operator, search_name_count';
|
||||
$sSQL .= ' FROM word ';
|
||||
$sSQL .= ' WHERE word_token in ('.join(',', $this->oDB->getDBQuotedList($aTokens)).')';
|
||||
$sSQL .= ' WHERE word_token in ('.join(',', array_map('getDBQuoted', $aTokens)).')';
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
@@ -832,7 +830,7 @@ class Geocode
|
||||
if ($aFilterSql) {
|
||||
$sSQL = join(' UNION ', $aFilterSql);
|
||||
Debug::printSQL($sSQL);
|
||||
$aFilteredIDs = $this->oDB->getCol($sSQL);
|
||||
$aFilteredIDs = chksql($this->oDB->getCol($sSQL));
|
||||
}
|
||||
|
||||
$tempIDs = array();
|
||||
|
||||
@@ -52,7 +52,7 @@ class PlaceLookup
|
||||
{
|
||||
$aLangs = $oParams->getPreferredLanguages();
|
||||
$this->aLangPrefOrderSql =
|
||||
'ARRAY['.join(',', $this->oDB->getDBQuotedList($aLangs)).']';
|
||||
'ARRAY['.join(',', array_map('getDBQuoted', $aLangs)).']';
|
||||
|
||||
$this->bExtraTags = $oParams->getBool('extratags', false);
|
||||
$this->bNameDetails = $oParams->getBool('namedetails', false);
|
||||
@@ -132,9 +132,8 @@ class PlaceLookup
|
||||
|
||||
public function setLanguagePreference($aLangPrefOrder)
|
||||
{
|
||||
$this->aLangPrefOrderSql = $this->oDB->getArraySQL(
|
||||
$this->oDB->getDBQuotedList($aLangPrefOrder)
|
||||
);
|
||||
$this->aLangPrefOrderSql =
|
||||
'ARRAY['.join(',', array_map('getDBQuoted', $aLangPrefOrder)).']';
|
||||
}
|
||||
|
||||
private function addressImportanceSql($sGeometry, $sPlaceId)
|
||||
@@ -163,8 +162,8 @@ class PlaceLookup
|
||||
|
||||
public function lookupOSMID($sType, $iID)
|
||||
{
|
||||
$sSQL = 'select place_id from placex where osm_type = :type and osm_id = :id';
|
||||
$iPlaceID = $this->oDB->getOne($sSQL, array(':type' => $sType, ':id' => $iID));
|
||||
$sSQL = "select place_id from placex where osm_type = '".$sType."' and osm_id = ".$iID;
|
||||
$iPlaceID = chksql($this->oDB->getOne($sSQL));
|
||||
|
||||
if (!$iPlaceID) {
|
||||
return null;
|
||||
@@ -425,10 +424,9 @@ class PlaceLookup
|
||||
|
||||
$sSQL = join(' UNION ', $aSubSelects);
|
||||
Debug::printSQL($sSQL);
|
||||
$aPlaces = $this->oDB->getAll($sSQL, null, 'Could not lookup place');
|
||||
$aPlaces = chksql($this->oDB->getAll($sSQL), 'Could not lookup place');
|
||||
|
||||
foreach ($aPlaces as &$aPlace) {
|
||||
$aPlace['importance'] = (float) $aPlace['importance'];
|
||||
if ($this->bAddressDetails) {
|
||||
// to get addressdetails for tiger data, the housenumber is needed
|
||||
$aPlace['address'] = new AddressDetails(
|
||||
@@ -515,9 +513,9 @@ class PlaceLookup
|
||||
$sSQL .= $sFrom;
|
||||
}
|
||||
|
||||
$aPointPolygon = $this->oDB->getRow($sSQL, null, 'Could not get outline');
|
||||
$aPointPolygon = chksql($this->oDB->getRow($sSQL), 'Could not get outline');
|
||||
|
||||
if ($aPointPolygon && $aPointPolygon['place_id']) {
|
||||
if ($aPointPolygon['place_id']) {
|
||||
if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null) {
|
||||
$aOutlineResult['lat'] = $aPointPolygon['centrelat'];
|
||||
$aOutlineResult['lon'] = $aPointPolygon['centrelon'];
|
||||
|
||||
@@ -36,8 +36,8 @@ class ReverseGeocode
|
||||
13 => 18,
|
||||
14 => 22, // Suburb
|
||||
15 => 22,
|
||||
16 => 26, // major street
|
||||
17 => 27, // minor street
|
||||
16 => 26, // Street, TODO: major street?
|
||||
17 => 26,
|
||||
18 => 30, // or >, Building
|
||||
19 => 30, // or >, Building
|
||||
);
|
||||
@@ -63,9 +63,8 @@ class ReverseGeocode
|
||||
$sSQL .= ' and indexed_status = 0 and startnumber is not NULL ';
|
||||
$sSQL .= ' ORDER BY distance ASC limit 1';
|
||||
|
||||
return $this->oDB->getRow(
|
||||
$sSQL,
|
||||
null,
|
||||
return chksql(
|
||||
$this->oDB->getRow($sSQL),
|
||||
'Could not determine closest housenumber on an osm interpolation line.'
|
||||
);
|
||||
}
|
||||
@@ -93,9 +92,8 @@ class ReverseGeocode
|
||||
$sSQL = 'SELECT country_code FROM country_osm_grid';
|
||||
$sSQL .= ' WHERE ST_CONTAINS(geometry, '.$sPointSQL.') LIMIT 1';
|
||||
|
||||
$sCountryCode = $this->oDB->getOne(
|
||||
$sSQL,
|
||||
null,
|
||||
$sCountryCode = chksql(
|
||||
$this->oDB->getOne($sSQL),
|
||||
'Could not determine country polygon containing the point.'
|
||||
);
|
||||
if ($sCountryCode) {
|
||||
@@ -117,7 +115,10 @@ class ReverseGeocode
|
||||
$sSQL .= ' LIMIT 1';
|
||||
|
||||
if (CONST_Debug) var_dump($sSQL);
|
||||
$aPlace = $this->oDB->getRow($sSQL, null, 'Could not determine place node.');
|
||||
$aPlace = chksql(
|
||||
$this->oDB->getRow($sSQL),
|
||||
'Could not determine place node.'
|
||||
);
|
||||
if ($aPlace) {
|
||||
return new Result($aPlace['place_id']);
|
||||
}
|
||||
@@ -133,7 +134,10 @@ class ReverseGeocode
|
||||
$sSQL .= ' ORDER BY distance ASC';
|
||||
|
||||
if (CONST_Debug) var_dump($sSQL);
|
||||
$aPlace = $this->oDB->getRow($sSQL, null, 'Could not determine place node.');
|
||||
$aPlace = chksql(
|
||||
$this->oDB->getRow($sSQL),
|
||||
'Could not determine place node.'
|
||||
);
|
||||
if ($aPlace) {
|
||||
return new Result($aPlace['place_id']);
|
||||
}
|
||||
@@ -174,8 +178,10 @@ class ReverseGeocode
|
||||
$sSQL .= ' WHERE ST_CONTAINS(geometry, '.$sPointSQL.' )';
|
||||
$sSQL .= ' ORDER BY rank_address DESC LIMIT 1';
|
||||
|
||||
$aPoly = $this->oDB->getRow($sSQL, null, 'Could not determine polygon containing the point.');
|
||||
|
||||
$aPoly = chksql(
|
||||
$this->oDB->getRow($sSQL),
|
||||
'Could not determine polygon containing the point.'
|
||||
);
|
||||
if ($aPoly) {
|
||||
// if a polygon is found, search for placenodes begins ...
|
||||
$iParentPlaceID = $aPoly['parent_place_id'];
|
||||
@@ -207,7 +213,10 @@ class ReverseGeocode
|
||||
$sSQL .= ' LIMIT 1';
|
||||
|
||||
if (CONST_Debug) var_dump($sSQL);
|
||||
$aPlacNode = $this->oDB->getRow($sSQL, null, 'Could not determine place node.');
|
||||
$aPlacNode = chksql(
|
||||
$this->oDB->getRow($sSQL),
|
||||
'Could not determine place node.'
|
||||
);
|
||||
if ($aPlacNode) {
|
||||
return $aPlacNode;
|
||||
}
|
||||
@@ -246,7 +255,12 @@ class ReverseGeocode
|
||||
$sSQL .= ' placex';
|
||||
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, '.$fSearchDiam.')';
|
||||
$sSQL .= ' AND';
|
||||
$sSQL .= ' rank_address between 26 and '.$iMaxRank;
|
||||
// only streets
|
||||
if ($iMaxRank == 26) {
|
||||
$sSQL .= ' rank_address = 26';
|
||||
} else {
|
||||
$sSQL .= ' rank_address between 26 and '.$iMaxRank;
|
||||
}
|
||||
$sSQL .= ' and (name is not null or housenumber is not null';
|
||||
$sSQL .= ' or rank_address between 26 and 27)';
|
||||
$sSQL .= ' and (rank_address between 26 and 27';
|
||||
@@ -257,7 +271,10 @@ class ReverseGeocode
|
||||
$sSQL .= ' OR ST_DWithin('.$sPointSQL.', centroid, '.$fSearchDiam.'))';
|
||||
$sSQL .= ' ORDER BY distance ASC limit 1';
|
||||
if (CONST_Debug) var_dump($sSQL);
|
||||
$aPlace = $this->oDB->getRow($sSQL, null, 'Could not determine closest place.');
|
||||
$aPlace = chksql(
|
||||
$this->oDB->getRow($sSQL),
|
||||
'Could not determine closest place.'
|
||||
);
|
||||
|
||||
if (CONST_Debug) var_dump($aPlace);
|
||||
if ($aPlace) {
|
||||
@@ -299,14 +316,17 @@ class ReverseGeocode
|
||||
// radius ?
|
||||
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, 0.001)';
|
||||
$sSQL .= ' AND parent_place_id = '.$iPlaceID;
|
||||
$sSQL .= ' and rank_address > 28';
|
||||
$sSQL .= ' and rank_address != 28';
|
||||
$sSQL .= ' and ST_GeometryType(geometry) != \'ST_LineString\'';
|
||||
$sSQL .= ' and (name is not null or housenumber is not null)';
|
||||
$sSQL .= ' and class not in (\'boundary\')';
|
||||
$sSQL .= ' and indexed_status = 0 and linked_place_id is null';
|
||||
$sSQL .= ' ORDER BY distance ASC limit 1';
|
||||
if (CONST_Debug) var_dump($sSQL);
|
||||
$aStreet = $this->oDB->getRow($sSQL, null, 'Could not determine closest place.');
|
||||
$aStreet = chksql(
|
||||
$this->oDB->getRow($sSQL),
|
||||
'Could not determine closest place.'
|
||||
);
|
||||
if ($aStreet) {
|
||||
if (CONST_Debug) var_dump($aStreet);
|
||||
$oResult = new Result($aStreet['place_id']);
|
||||
@@ -327,7 +347,10 @@ class ReverseGeocode
|
||||
$sSQL .= ' AND ST_DWithin('.$sPointSQL.', linegeo, 0.001)';
|
||||
$sSQL .= ' ORDER BY distance ASC limit 1';
|
||||
if (CONST_Debug) var_dump($sSQL);
|
||||
$aPlaceTiger = $this->oDB->getRow($sSQL, null, 'Could not determine closest Tiger place.');
|
||||
$aPlaceTiger = chksql(
|
||||
$this->oDB->getRow($sSQL),
|
||||
'Could not determine closest Tiger place.'
|
||||
);
|
||||
if ($aPlaceTiger) {
|
||||
if (CONST_Debug) var_dump('found Tiger housenumber', $aPlaceTiger);
|
||||
$oResult = new Result($aPlaceTiger['place_id'], Result::TABLE_TIGER);
|
||||
|
||||
@@ -126,7 +126,7 @@ class SearchContext
|
||||
* The viewbox may be bounded which means that no search results
|
||||
* must be outside the viewbox.
|
||||
*
|
||||
* @param object $oDB Nominatim::DB instance to use for computing the box.
|
||||
* @param object $oDB DB connection to use for computing the box.
|
||||
* @param string[] $aRoutePoints List of x,y coordinates along a route.
|
||||
* @param float $fRouteWidth Buffer around the route to use.
|
||||
* @param bool $bBounded True if the viewbox bounded.
|
||||
@@ -146,11 +146,11 @@ class SearchContext
|
||||
$this->sqlViewboxCentre .= ")'::geometry,4326)";
|
||||
|
||||
$sSQL = 'ST_BUFFER('.$this->sqlViewboxCentre.','.($fRouteWidth/69).')';
|
||||
$sGeom = $oDB->getOne('select '.$sSQL, null, 'Could not get small viewbox');
|
||||
$sGeom = chksql($oDB->getOne('select '.$sSQL), 'Could not get small viewbox');
|
||||
$this->sqlViewboxSmall = "'".$sGeom."'::geometry";
|
||||
|
||||
$sSQL = 'ST_BUFFER('.$this->sqlViewboxCentre.','.($fRouteWidth/30).')';
|
||||
$sGeom = $oDB->getOne('select '.$sSQL, null, 'Could not get large viewbox');
|
||||
$sGeom = chksql($oDB->getOne('select '.$sSQL), 'Could not get large viewbox');
|
||||
$this->sqlViewboxLarge = "'".$sGeom."'::geometry";
|
||||
}
|
||||
|
||||
|
||||
@@ -404,7 +404,7 @@ class SearchDescription
|
||||
/**
|
||||
* Query database for places that match this search.
|
||||
*
|
||||
* @param object $oDB Nominatim::DB instance to use.
|
||||
* @param object $oDB Database connection to use.
|
||||
* @param integer $iMinRank Minimum address rank to restrict search to.
|
||||
* @param integer $iMaxRank Maximum address rank to restrict search to.
|
||||
* @param integer $iLimit Maximum number of results.
|
||||
@@ -479,7 +479,7 @@ class SearchDescription
|
||||
$sSQL .= ' WHERE place_id in ('.$sPlaceIds.')';
|
||||
$sSQL .= " AND postcode != '".$this->sPostcode."'";
|
||||
Debug::printSQL($sSQL);
|
||||
$aFilteredPlaceIDs = $oDB->getCol($sSQL);
|
||||
$aFilteredPlaceIDs = chksql($oDB->getCol($sSQL));
|
||||
if ($aFilteredPlaceIDs) {
|
||||
foreach ($aFilteredPlaceIDs as $iPlaceId) {
|
||||
$aResults[$iPlaceId]->iResultRank++;
|
||||
@@ -504,10 +504,8 @@ class SearchDescription
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
$iPlaceId = $oDB->getOne($sSQL);
|
||||
|
||||
$aResults = array();
|
||||
if ($iPlaceId) {
|
||||
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
|
||||
$aResults[$iPlaceId] = new Result($iPlaceId);
|
||||
}
|
||||
|
||||
@@ -523,7 +521,8 @@ class SearchDescription
|
||||
$aDBResults = array();
|
||||
$sPoiTable = $this->poiTable();
|
||||
|
||||
if ($oDB->tableExists($sPoiTable)) {
|
||||
$sSQL = 'SELECT count(*) FROM pg_tables WHERE tablename = \''.$sPoiTable."'";
|
||||
if (chksql($oDB->getOne($sSQL))) {
|
||||
$sSQL = 'SELECT place_id FROM '.$sPoiTable.' ct';
|
||||
if ($this->oContext->sqlCountryList) {
|
||||
$sSQL .= ' JOIN placex USING (place_id)';
|
||||
@@ -543,14 +542,14 @@ class SearchDescription
|
||||
} elseif ($this->oContext->hasNearPoint()) {
|
||||
$sSQL .= ' ORDER BY '.$this->oContext->distanceSQL('ct.centroid').' ASC';
|
||||
}
|
||||
$sSQL .= " LIMIT $iLimit";
|
||||
$sSQL .= " limit $iLimit";
|
||||
Debug::printSQL($sSQL);
|
||||
$aDBResults = $oDB->getCol($sSQL);
|
||||
$aDBResults = chksql($oDB->getCol($sSQL));
|
||||
}
|
||||
|
||||
if ($this->oContext->hasNearPoint()) {
|
||||
$sSQL = 'SELECT place_id FROM placex WHERE ';
|
||||
$sSQL .= 'class = :class and type = :type';
|
||||
$sSQL .= 'class=\''.$this->sClass."' and type='".$this->sType."'";
|
||||
$sSQL .= ' AND '.$this->oContext->withinSQL('geometry');
|
||||
$sSQL .= ' AND linked_place_id is null';
|
||||
if ($this->oContext->sqlCountryList) {
|
||||
@@ -559,10 +558,7 @@ class SearchDescription
|
||||
$sSQL .= ' ORDER BY '.$this->oContext->distanceSQL('centroid').' ASC';
|
||||
$sSQL .= " LIMIT $iLimit";
|
||||
Debug::printSQL($sSQL);
|
||||
$aDBResults = $oDB->getCol(
|
||||
$sSQL,
|
||||
array(':class' => $this->sClass, ':type' => $this->sType)
|
||||
);
|
||||
$aDBResults = chksql($oDB->getCol($sSQL));
|
||||
}
|
||||
|
||||
$aResults = array();
|
||||
@@ -581,23 +577,20 @@ class SearchDescription
|
||||
$sSQL .= ', search_name s ';
|
||||
$sSQL .= 'WHERE s.place_id = p.parent_place_id ';
|
||||
$sSQL .= 'AND array_cat(s.nameaddress_vector, s.name_vector)';
|
||||
$sSQL .= ' @> '.$oDB->getArraySQL($this->aAddress).' AND ';
|
||||
$sSQL .= ' @> '.getArraySQL($this->aAddress).' AND ';
|
||||
} else {
|
||||
$sSQL .= 'WHERE ';
|
||||
}
|
||||
|
||||
$sSQL .= "p.postcode = '".reset($this->aName)."'";
|
||||
$sSQL .= $this->countryCodeSQL(' AND p.country_code');
|
||||
if ($this->oContext->bViewboxBounded) {
|
||||
$sSQL .= ' AND ST_Intersects('.$this->oContext->sqlViewboxSmall.', geometry)';
|
||||
}
|
||||
$sSQL .= $this->oContext->excludeSQL(' AND p.place_id');
|
||||
$sSQL .= " LIMIT $iLimit";
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
$aResults = array();
|
||||
foreach ($oDB->getCol($sSQL) as $iPlaceId) {
|
||||
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
|
||||
$aResults[$iPlaceId] = new Result($iPlaceId, Result::TABLE_POSTCODE);
|
||||
}
|
||||
|
||||
@@ -640,14 +633,14 @@ class SearchDescription
|
||||
}
|
||||
|
||||
if (!empty($this->aName)) {
|
||||
$aTerms[] = 'name_vector @> '.$oDB->getArraySQL($this->aName);
|
||||
$aTerms[] = 'name_vector @> '.getArraySQL($this->aName);
|
||||
}
|
||||
if (!empty($this->aAddress)) {
|
||||
// For infrequent name terms disable index usage for address
|
||||
if ($this->bRareName) {
|
||||
$aTerms[] = 'array_cat(nameaddress_vector,ARRAY[]::integer[]) @> '.$oDB->getArraySQL($this->aAddress);
|
||||
$aTerms[] = 'array_cat(nameaddress_vector,ARRAY[]::integer[]) @> '.getArraySQL($this->aAddress);
|
||||
} else {
|
||||
$aTerms[] = 'nameaddress_vector @> '.$oDB->getArraySQL($this->aAddress);
|
||||
$aTerms[] = 'nameaddress_vector @> '.getArraySQL($this->aAddress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,7 +695,7 @@ class SearchDescription
|
||||
if (!empty($this->aFullNameAddress)) {
|
||||
$sExactMatchSQL = ' ( ';
|
||||
$sExactMatchSQL .= ' SELECT count(*) FROM ( ';
|
||||
$sExactMatchSQL .= ' SELECT unnest('.$oDB->getArraySQL($this->aFullNameAddress).')';
|
||||
$sExactMatchSQL .= ' SELECT unnest('.getArraySQL($this->aFullNameAddress).')';
|
||||
$sExactMatchSQL .= ' INTERSECT ';
|
||||
$sExactMatchSQL .= ' SELECT unnest(nameaddress_vector)';
|
||||
$sExactMatchSQL .= ' ) s';
|
||||
@@ -727,7 +720,10 @@ class SearchDescription
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
$aDBResults = $oDB->getAll($sSQL, null, 'Could not get places for search terms.');
|
||||
$aDBResults = chksql(
|
||||
$oDB->getAll($sSQL),
|
||||
'Could not get places for search terms.'
|
||||
);
|
||||
|
||||
foreach ($aDBResults as $aResult) {
|
||||
$oResult = new Result($aResult['place_id']);
|
||||
@@ -757,7 +753,7 @@ class SearchDescription
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
// XXX should inherit the exactMatches from its parent
|
||||
foreach ($oDB->getCol($sSQL) as $iPlaceId) {
|
||||
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
|
||||
$aResults[$iPlaceId] = new Result($iPlaceId);
|
||||
}
|
||||
|
||||
@@ -783,7 +779,7 @@ class SearchDescription
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
foreach ($oDB->getCol($sSQL) as $iPlaceId) {
|
||||
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
|
||||
$oResult = new Result($iPlaceId, Result::TABLE_OSMLINE);
|
||||
$oResult->iHouseNumber = $iHousenumber;
|
||||
$aResults[$iPlaceId] = $oResult;
|
||||
@@ -799,7 +795,7 @@ class SearchDescription
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
foreach ($oDB->getCol($sSQL) as $iPlaceId) {
|
||||
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
|
||||
$aResults[$iPlaceId] = new Result($iPlaceId, Result::TABLE_AUX);
|
||||
}
|
||||
}
|
||||
@@ -820,7 +816,7 @@ class SearchDescription
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
foreach ($oDB->getCol($sSQL) as $iPlaceId) {
|
||||
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
|
||||
$oResult = new Result($iPlaceId, Result::TABLE_TIGER);
|
||||
$oResult->iHouseNumber = $iHousenumber;
|
||||
$aResults[$iPlaceId] = $oResult;
|
||||
@@ -854,7 +850,7 @@ class SearchDescription
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
foreach ($oDB->getCol($sSQL) as $iPlaceId) {
|
||||
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
|
||||
$aResults[$iPlaceId] = new Result($iPlaceId);
|
||||
}
|
||||
}
|
||||
@@ -862,11 +858,12 @@ class SearchDescription
|
||||
// NEAR and IN are handled the same
|
||||
if ($this->iOperator == Operator::TYPE || $this->iOperator == Operator::NEAR) {
|
||||
$sClassTable = $this->poiTable();
|
||||
$bCacheTable = $oDB->tableExists($sClassTable);
|
||||
$sSQL = "SELECT count(*) FROM pg_tables WHERE tablename = '$sClassTable'";
|
||||
$bCacheTable = (bool) chksql($oDB->getOne($sSQL));
|
||||
|
||||
$sSQL = "SELECT min(rank_search) FROM placex WHERE place_id in ($sPlaceIDs)";
|
||||
Debug::printSQL($sSQL);
|
||||
$iMaxRank = (int) $oDB->getOne($sSQL);
|
||||
$iMaxRank = (int)chksql($oDB->getOne($sSQL));
|
||||
|
||||
// For state / country level searches the normal radius search doesn't work very well
|
||||
$sPlaceGeom = false;
|
||||
@@ -879,7 +876,7 @@ class SearchDescription
|
||||
$sSQL .= ' ORDER BY rank_search ASC ';
|
||||
$sSQL .= ' LIMIT 1';
|
||||
Debug::printSQL($sSQL);
|
||||
$sPlaceGeom = $oDB->getOne($sSQL);
|
||||
$sPlaceGeom = chksql($oDB->getOne($sSQL));
|
||||
}
|
||||
|
||||
if ($sPlaceGeom) {
|
||||
@@ -889,7 +886,7 @@ class SearchDescription
|
||||
$sSQL = 'SELECT place_id FROM placex';
|
||||
$sSQL .= " WHERE place_id in ($sPlaceIDs) and rank_search < $iMaxRank";
|
||||
Debug::printSQL($sSQL);
|
||||
$aPlaceIDs = $oDB->getCol($sSQL);
|
||||
$aPlaceIDs = chksql($oDB->getCol($sSQL));
|
||||
$sPlaceIDs = join(',', $aPlaceIDs);
|
||||
}
|
||||
|
||||
@@ -935,7 +932,7 @@ class SearchDescription
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
foreach ($oDB->getCol($sSQL) as $iPlaceId) {
|
||||
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
|
||||
$aResults[$iPlaceId] = new Result($iPlaceId);
|
||||
}
|
||||
} else {
|
||||
@@ -967,7 +964,7 @@ class SearchDescription
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
foreach ($oDB->getCol($sSQL) as $iPlaceId) {
|
||||
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
|
||||
$aResults[$iPlaceId] = new Result($iPlaceId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Nominatim;
|
||||
|
||||
use Exception;
|
||||
use PEAR;
|
||||
|
||||
class Status
|
||||
{
|
||||
@@ -15,18 +16,12 @@ class Status
|
||||
|
||||
public function status()
|
||||
{
|
||||
if (!$this->oDB) {
|
||||
if (!$this->oDB || PEAR::isError($this->oDB)) {
|
||||
throw new Exception('No database', 700);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->oDB->connect();
|
||||
} catch (\Nominatim\DatabaseError $e) {
|
||||
throw new Exception('Database connection failed', 700);
|
||||
}
|
||||
|
||||
$sStandardWord = $this->oDB->getOne("SELECT make_standard_name('a')");
|
||||
if ($sStandardWord === false) {
|
||||
if (PEAR::isError($sStandardWord)) {
|
||||
throw new Exception('Module failed', 701);
|
||||
}
|
||||
|
||||
@@ -37,7 +32,7 @@ class Status
|
||||
$sSQL = 'SELECT word_id, word_token, word, class, type, country_code, ';
|
||||
$sSQL .= "operator, search_name_count FROM word WHERE word_token IN (' a')";
|
||||
$iWordID = $this->oDB->getOne($sSQL);
|
||||
if ($iWordID === false) {
|
||||
if (PEAR::isError($iWordID)) {
|
||||
throw new Exception('Query failed', 703);
|
||||
}
|
||||
if (!$iWordID) {
|
||||
@@ -50,7 +45,7 @@ class Status
|
||||
$sSQL = 'SELECT EXTRACT(EPOCH FROM lastimportdate) FROM import_status LIMIT 1';
|
||||
$iDataDateEpoch = $this->oDB->getOne($sSQL);
|
||||
|
||||
if ($iDataDateEpoch === false) {
|
||||
if (PEAR::isError($iDataDateEpoch)) {
|
||||
throw Exception('Data date query failed '.$iDataDateEpoch->getMessage(), 705);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ class TokenList
|
||||
/**
|
||||
* Add token information from the word table in the database.
|
||||
*
|
||||
* @param object $oDB Nominatim::DB instance.
|
||||
* @param object $oDB Database connection.
|
||||
* @param string[] $aTokens List of tokens to look up in the database.
|
||||
* @param string[] $aCountryCodes List of country restrictions.
|
||||
* @param string $sNormQuery Normalized query string.
|
||||
@@ -85,11 +85,11 @@ class TokenList
|
||||
$sSQL = 'SELECT word_id, word_token, word, class, type, country_code,';
|
||||
$sSQL .= ' operator, coalesce(search_name_count, 0) as count';
|
||||
$sSQL .= ' FROM word WHERE word_token in (';
|
||||
$sSQL .= join(',', $oDB->getDBQuotedList($aTokens)).')';
|
||||
$sSQL .= join(',', array_map('getDBQuoted', $aTokens)).')';
|
||||
|
||||
Debug::printSQL($sSQL);
|
||||
|
||||
$aDBWords = $oDB->getAll($sSQL, null, 'Could not get word tokens.');
|
||||
$aDBWords = chksql($oDB->getAll($sSQL), 'Could not get word tokens.');
|
||||
|
||||
foreach ($aDBWords as $aWord) {
|
||||
$oToken = null;
|
||||
|
||||
11
lib/cmd.php
11
lib/cmd.php
@@ -120,6 +120,15 @@ function showUsage($aSpec, $bExit = false, $sError = false)
|
||||
exit;
|
||||
}
|
||||
|
||||
function chksql($oSql, $sMsg = false)
|
||||
{
|
||||
if (PEAR::isError($oSql)) {
|
||||
fail($sMsg || $oSql->getMessage(), $oSql->userinfo);
|
||||
}
|
||||
|
||||
return $oSql;
|
||||
}
|
||||
|
||||
function info($sMsg)
|
||||
{
|
||||
echo date('Y-m-d H:i:s == ').$sMsg."\n";
|
||||
@@ -146,7 +155,7 @@ function repeatWarnings()
|
||||
function runSQLScript($sScript, $bfatal = true, $bVerbose = false, $bIgnoreErrors = false)
|
||||
{
|
||||
// Convert database DSN to psql parameters
|
||||
$aDSNInfo = \Nominatim\DB::parseDSN(CONST_Database_DSN);
|
||||
$aDSNInfo = DB::parseDSN(CONST_Database_DSN);
|
||||
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
|
||||
$sCMD = 'psql -p '.$aDSNInfo['port'].' -d '.$aDSNInfo['database'];
|
||||
if (isset($aDSNInfo['hostspec']) && $aDSNInfo['hostspec']) {
|
||||
|
||||
43
lib/db.php
Normal file
43
lib/db.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
require_once('DB.php');
|
||||
|
||||
|
||||
function &getDB($bNew = false, $bPersistent = false)
|
||||
{
|
||||
// Get the database object
|
||||
$oDB = chksql(
|
||||
DB::connect(CONST_Database_DSN.($bNew?'?new_link=true':''), $bPersistent),
|
||||
'Failed to establish database connection'
|
||||
);
|
||||
$oDB->setFetchMode(DB_FETCHMODE_ASSOC);
|
||||
$oDB->query("SET DateStyle TO 'sql,european'");
|
||||
$oDB->query("SET client_encoding TO 'utf-8'");
|
||||
$iMaxExecution = ini_get('max_execution_time') * 1000;
|
||||
if ($iMaxExecution > 0) $oDB->query("SET statement_timeout TO $iMaxExecution");
|
||||
return $oDB;
|
||||
}
|
||||
|
||||
function getDBQuoted($s)
|
||||
{
|
||||
return "'".pg_escape_string($s)."'";
|
||||
}
|
||||
|
||||
function getArraySQL($a)
|
||||
{
|
||||
return 'ARRAY['.join(',', $a).']';
|
||||
}
|
||||
|
||||
function getPostgresVersion(&$oDB)
|
||||
{
|
||||
$sVersionString = $oDB->getOne('SHOW server_version_num');
|
||||
preg_match('#([0-9]?[0-9])([0-9][0-9])[0-9][0-9]#', $sVersionString, $aMatches);
|
||||
return (float) ($aMatches[1].'.'.$aMatches[2]);
|
||||
}
|
||||
|
||||
function getPostgisVersion(&$oDB)
|
||||
{
|
||||
$sVersionString = $oDB->getOne('select postgis_lib_version()');
|
||||
preg_match('#^([0-9]+)[.]([0-9]+)[.]#', $sVersionString, $aMatches);
|
||||
return (float) ($aMatches[1].'.'.$aMatches[2]);
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
require_once('init.php');
|
||||
require_once('ParameterParser.php');
|
||||
require_once('DatabaseError.php');
|
||||
require_once(CONST_Debug ? 'DebugHtml.php' : 'DebugNone.php');
|
||||
|
||||
/***************************************************************************
|
||||
@@ -10,6 +11,15 @@ require_once(CONST_Debug ? 'DebugHtml.php' : 'DebugNone.php');
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
function chksql($oSql, $sMsg = 'Database request failed')
|
||||
{
|
||||
if (!PEAR::isError($oSql)) return $oSql;
|
||||
|
||||
throw new Nominatim\DatabaseError($sMsg, 500, null, $oSql);
|
||||
}
|
||||
|
||||
|
||||
function userError($sMsg)
|
||||
{
|
||||
throw new Exception($sMsg, 400);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once(CONST_BasePath.'/lib/lib.php');
|
||||
require_once(CONST_BasePath.'/lib/DB.php');
|
||||
require_once(CONST_BasePath.'/lib/db.php');
|
||||
|
||||
if (get_magic_quotes_gpc()) {
|
||||
echo "Please disable magic quotes in your php.ini configuration\n";
|
||||
|
||||
@@ -4,7 +4,7 @@ function fail($sError, $sUserError = false)
|
||||
{
|
||||
if (!$sUserError) $sUserError = $sError;
|
||||
error_log('ERROR: '.$sError);
|
||||
var_dump($sUserError)."\n";
|
||||
echo $sUserError."\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
22
lib/log.php
22
lib/log.php
@@ -36,18 +36,8 @@ function logStart(&$oDB, $sType = '', $sQuery = '', $aLanguageList = array())
|
||||
$sUserAgent = $_SERVER['HTTP_USER_AGENT'];
|
||||
else $sUserAgent = '';
|
||||
$sSQL = 'insert into new_query_log (type,starttime,query,ipaddress,useragent,language,format,searchterm)';
|
||||
$sSQL .= ' values ('.
|
||||
$sSQL .= join(',', $oDB->getDBQuotedList(array(
|
||||
$sType,
|
||||
$hLog[0],
|
||||
$hLog[2],
|
||||
$hLog[1],
|
||||
$sUserAgent,
|
||||
join(',', $aLanguageList),
|
||||
$sOutputFormat,
|
||||
$hLog[3]
|
||||
)));
|
||||
$sSQL .= ')';
|
||||
$sSQL .= ' values ('.getDBQuoted($sType).','.getDBQuoted($hLog[0]).','.getDBQuoted($hLog[2]);
|
||||
$sSQL .= ','.getDBQuoted($hLog[1]).','.getDBQuoted($sUserAgent).','.getDBQuoted(join(',', $aLanguageList)).','.getDBQuoted($sOutputFormat).','.getDBQuoted($hLog[3]).')';
|
||||
$oDB->query($sSQL);
|
||||
}
|
||||
|
||||
@@ -63,10 +53,10 @@ function logEnd(&$oDB, $hLog, $iNumResults)
|
||||
if (!$aEndTime[1]) $aEndTime[1] = '0';
|
||||
$sEndTime = date('Y-m-d H:i:s', $aEndTime[0]).'.'.$aEndTime[1];
|
||||
|
||||
$sSQL = 'update new_query_log set endtime = '.$oDB->getDBQuoted($sEndTime).', results = '.$iNumResults;
|
||||
$sSQL .= ' where starttime = '.$oDB->getDBQuoted($hLog[0]);
|
||||
$sSQL .= ' and ipaddress = '.$oDB->getDBQuoted($hLog[1]);
|
||||
$sSQL .= ' and query = '.$oDB->getDBQuoted($hLog[2]);
|
||||
$sSQL = 'update new_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[2]);
|
||||
$oDB->query($sSQL);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,21 +53,21 @@ class AddressLevelParser
|
||||
*/
|
||||
public function createTable($oDB, $sTable)
|
||||
{
|
||||
$oDB->exec('DROP TABLE IF EXISTS '.$sTable);
|
||||
chksql($oDB->query('DROP TABLE IF EXISTS '.$sTable));
|
||||
$sSql = 'CREATE TABLE '.$sTable;
|
||||
$sSql .= '(country_code varchar(2), class TEXT, type TEXT,';
|
||||
$sSql .= ' rank_search SMALLINT, rank_address SMALLINT)';
|
||||
$oDB->exec($sSql);
|
||||
chksql($oDB->query($sSql));
|
||||
|
||||
$sSql = 'CREATE UNIQUE INDEX ON '.$sTable.' (country_code, class, type)';
|
||||
$oDB->exec($sSql);
|
||||
$sSql = 'CREATE UNIQUE INDEX ON '.$sTable.'(country_code, class, type)';
|
||||
chksql($oDB->query($sSql));
|
||||
|
||||
$sSql = 'INSERT INTO '.$sTable.' VALUES ';
|
||||
foreach ($this->aLevels as $aLevel) {
|
||||
$aCountries = array();
|
||||
if (isset($aLevel['countries'])) {
|
||||
foreach ($aLevel['countries'] as $sCountry) {
|
||||
$aCountries[$sCountry] = $oDB->getDBQuoted($sCountry);
|
||||
$aCountries[$sCountry] = getDBQuoted($sCountry);
|
||||
}
|
||||
} else {
|
||||
$aCountries['NULL'] = 'NULL';
|
||||
@@ -75,8 +75,8 @@ class AddressLevelParser
|
||||
foreach ($aLevel['tags'] as $sKey => $aValues) {
|
||||
foreach ($aValues as $sValue => $mRanks) {
|
||||
$aFields = array(
|
||||
$oDB->getDBQuoted($sKey),
|
||||
$sValue ? $oDB->getDBQuoted($sValue) : 'NULL'
|
||||
getDBQuoted($sKey),
|
||||
$sValue ? getDBQuoted($sValue) : 'NULL'
|
||||
);
|
||||
if (is_array($mRanks)) {
|
||||
$aFields[] = (string) $mRanks[0];
|
||||
@@ -93,6 +93,6 @@ class AddressLevelParser
|
||||
}
|
||||
}
|
||||
}
|
||||
$oDB->exec(rtrim($sSql, ','));
|
||||
chksql($oDB->query(rtrim($sSql, ',')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class SetupFunctions
|
||||
info('module path: ' . $this->sModulePath);
|
||||
|
||||
// parse database string
|
||||
$this->aDSNInfo = \Nominatim\DB::parseDSN(CONST_Database_DSN);
|
||||
$this->aDSNInfo = array_filter(\DB::parseDSN(CONST_Database_DSN));
|
||||
if (!isset($this->aDSNInfo['port'])) {
|
||||
$this->aDSNInfo['port'] = 5432;
|
||||
}
|
||||
@@ -74,9 +74,8 @@ class SetupFunctions
|
||||
public function createDB()
|
||||
{
|
||||
info('Create DB');
|
||||
$oDB = new \Nominatim\DB;
|
||||
|
||||
if ($oDB->databaseExists()) {
|
||||
$sDB = \DB::connect(CONST_Database_DSN, false);
|
||||
if (!\PEAR::isError($sDB)) {
|
||||
fail('database already exists ('.CONST_Database_DSN.')');
|
||||
}
|
||||
|
||||
@@ -95,15 +94,14 @@ class SetupFunctions
|
||||
|
||||
public function connect()
|
||||
{
|
||||
$this->oDB = new \Nominatim\DB();
|
||||
$this->oDB->connect();
|
||||
$this->oDB =& getDB();
|
||||
}
|
||||
|
||||
public function setupDB()
|
||||
{
|
||||
info('Setup DB');
|
||||
|
||||
$fPostgresVersion = $this->oDB->getPostgresVersion();
|
||||
$fPostgresVersion = getPostgresVersion($this->oDB);
|
||||
echo 'Postgres version found: '.$fPostgresVersion."\n";
|
||||
|
||||
if ($fPostgresVersion < 9.01) {
|
||||
@@ -116,7 +114,7 @@ class SetupFunctions
|
||||
// For extratags and namedetails the hstore_to_json converter is
|
||||
// needed which is only available from Postgresql 9.3+. For older
|
||||
// versions add a dummy function that returns nothing.
|
||||
$iNumFunc = $this->oDB->getOne("select count(*) from pg_proc where proname = 'hstore_to_json'");
|
||||
$iNumFunc = chksql($this->oDB->getOne("select count(*) from pg_proc where proname = 'hstore_to_json'"));
|
||||
|
||||
if ($iNumFunc == 0) {
|
||||
$this->pgsqlRunScript("create function hstore_to_json(dummy hstore) returns text AS 'select null::text' language sql immutable");
|
||||
@@ -124,7 +122,7 @@ class SetupFunctions
|
||||
}
|
||||
|
||||
|
||||
$fPostgisVersion = $this->oDB->getPostgisVersion();
|
||||
$fPostgisVersion = getPostgisVersion($this->oDB);
|
||||
echo 'Postgis version found: '.$fPostgisVersion."\n";
|
||||
|
||||
if ($fPostgisVersion < 2.1) {
|
||||
@@ -136,7 +134,7 @@ class SetupFunctions
|
||||
$this->pgsqlRunScript('ALTER FUNCTION ST_Distance_Spheroid(geometry, geometry, spheroid) RENAME TO ST_DistanceSpheroid');
|
||||
}
|
||||
|
||||
$i = $this->oDB->getOne("select count(*) from pg_user where usename = '".CONST_Database_Web_User."'");
|
||||
$i = chksql($this->oDB->getOne("select count(*) from pg_user where usename = '".CONST_Database_Web_User."'"));
|
||||
if ($i == 0) {
|
||||
echo "\nERROR: Web user '".CONST_Database_Web_User."' does not exist. Create it with:\n";
|
||||
echo "\n createuser ".CONST_Database_Web_User."\n\n";
|
||||
@@ -144,7 +142,9 @@ class SetupFunctions
|
||||
}
|
||||
|
||||
// Try accessing the C module, so we know early if something is wrong
|
||||
checkModulePresence(); // raises exception on failure
|
||||
if (!checkModulePresence()) {
|
||||
fail('error loading nominatim.so module');
|
||||
}
|
||||
|
||||
if (!file_exists(CONST_ExtraDataPath.'/country_osm_grid.sql.gz')) {
|
||||
echo 'Error: you need to download the country_osm_grid first:';
|
||||
@@ -216,7 +216,7 @@ class SetupFunctions
|
||||
|
||||
$this->runWithPgEnv($osm2pgsql);
|
||||
|
||||
if (!$this->sIgnoreErrors && !$this->oDB->getRow('select * from place limit 1')) {
|
||||
if (!$this->sIgnoreErrors && !chksql($this->oDB->getRow('select * from place limit 1'))) {
|
||||
fail('No Data');
|
||||
}
|
||||
}
|
||||
@@ -225,9 +225,11 @@ class SetupFunctions
|
||||
{
|
||||
info('Create Functions');
|
||||
|
||||
// Try accessing the C module, so we know early if something is wrong
|
||||
checkModulePresence(); // raises exception on failure
|
||||
|
||||
// Try accessing the C module, so we know eif something is wrong
|
||||
// update.php calls this function
|
||||
if (!checkModulePresence()) {
|
||||
fail('error loading nominatim.so module');
|
||||
}
|
||||
$this->createSqlFunctions();
|
||||
}
|
||||
|
||||
@@ -376,8 +378,7 @@ class SetupFunctions
|
||||
echo '.';
|
||||
|
||||
$sSQL = 'select distinct partition from country_name';
|
||||
$aPartitions = $this->oDB->getCol($sSQL);
|
||||
|
||||
$aPartitions = chksql($this->oDB->getCol($sSQL));
|
||||
if (!$this->bNoPartitions) $aPartitions[] = 0;
|
||||
foreach ($aPartitions as $sPartition) {
|
||||
$this->pgExec('TRUNCATE location_road_'.$sPartition);
|
||||
@@ -398,48 +399,34 @@ class SetupFunctions
|
||||
|
||||
info('Load Data');
|
||||
$sColumns = 'osm_type, osm_id, class, type, name, admin_level, address, extratags, geometry';
|
||||
|
||||
$aDBInstances = array();
|
||||
$iLoadThreads = max(1, $this->iInstances - 1);
|
||||
for ($i = 0; $i < $iLoadThreads; $i++) {
|
||||
// https://secure.php.net/manual/en/function.pg-connect.php
|
||||
$DSN = CONST_Database_DSN;
|
||||
$DSN = preg_replace('/^pgsql:/', '', $DSN);
|
||||
$DSN = preg_replace('/;/', ' ', $DSN);
|
||||
$aDBInstances[$i] = pg_connect($DSN, PGSQL_CONNECT_FORCE_NEW);
|
||||
pg_ping($aDBInstances[$i]);
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $iLoadThreads; $i++) {
|
||||
$aDBInstances[$i] =& getDB(true);
|
||||
$sSQL = "INSERT INTO placex ($sColumns) SELECT $sColumns FROM place WHERE osm_id % $iLoadThreads = $i";
|
||||
$sSQL .= " and not (class='place' and type='houses' and osm_type='W'";
|
||||
$sSQL .= " and ST_GeometryType(geometry) = 'ST_LineString')";
|
||||
$sSQL .= ' and ST_IsValid(geometry)';
|
||||
if ($this->bVerbose) echo "$sSQL\n";
|
||||
if (!pg_send_query($aDBInstances[$i], $sSQL)) {
|
||||
fail(pg_last_error($aDBInstances[$i]));
|
||||
if (!pg_send_query($aDBInstances[$i]->connection, $sSQL)) {
|
||||
fail(pg_last_error($aDBInstances[$i]->connection));
|
||||
}
|
||||
}
|
||||
|
||||
// last thread for interpolation lines
|
||||
// https://secure.php.net/manual/en/function.pg-connect.php
|
||||
$DSN = CONST_Database_DSN;
|
||||
$DSN = preg_replace('/^pgsql:/', '', $DSN);
|
||||
$DSN = preg_replace('/;/', ' ', $DSN);
|
||||
$aDBInstances[$iLoadThreads] = pg_connect($DSN, PGSQL_CONNECT_FORCE_NEW);
|
||||
pg_ping($aDBInstances[$iLoadThreads]);
|
||||
$aDBInstances[$iLoadThreads] =& getDB(true);
|
||||
$sSQL = 'insert into location_property_osmline';
|
||||
$sSQL .= ' (osm_id, address, linegeo)';
|
||||
$sSQL .= ' SELECT osm_id, address, geometry from place where ';
|
||||
$sSQL .= "class='place' and type='houses' and osm_type='W' and ST_GeometryType(geometry) = 'ST_LineString'";
|
||||
if ($this->bVerbose) echo "$sSQL\n";
|
||||
if (!pg_send_query($aDBInstances[$iLoadThreads], $sSQL)) {
|
||||
fail(pg_last_error($aDBInstances[$iLoadThreads]));
|
||||
if (!pg_send_query($aDBInstances[$iLoadThreads]->connection, $sSQL)) {
|
||||
fail(pg_last_error($aDBInstances[$iLoadThreads]->connection));
|
||||
}
|
||||
|
||||
$bFailed = false;
|
||||
for ($i = 0; $i <= $iLoadThreads; $i++) {
|
||||
while (($hPGresult = pg_get_result($aDBInstances[$i])) !== false) {
|
||||
while (($hPGresult = pg_get_result($aDBInstances[$i]->connection)) !== false) {
|
||||
$resultStatus = pg_result_status($hPGresult);
|
||||
// PGSQL_EMPTY_QUERY, PGSQL_COMMAND_OK, PGSQL_TUPLES_OK,
|
||||
// PGSQL_COPY_OUT, PGSQL_COPY_IN, PGSQL_BAD_RESPONSE,
|
||||
@@ -455,22 +442,17 @@ class SetupFunctions
|
||||
if ($bFailed) {
|
||||
fail('SQL errors loading placex and/or location_property_osmline tables');
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $this->iInstances; $i++) {
|
||||
pg_close($aDBInstances[$i]);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
info('Reanalysing database');
|
||||
$this->pgsqlRunScript('ANALYSE');
|
||||
|
||||
$sDatabaseDate = getDatabaseDate($this->oDB);
|
||||
$this->oDB->exec('TRUNCATE import_status');
|
||||
if (!$sDatabaseDate) {
|
||||
pg_query($this->oDB->connection, 'TRUNCATE import_status');
|
||||
if ($sDatabaseDate === false) {
|
||||
warn('could not determine database date.');
|
||||
} else {
|
||||
$sSQL = "INSERT INTO import_status (lastimportdate) VALUES('".$sDatabaseDate."')";
|
||||
$this->oDB->exec($sSQL);
|
||||
pg_query($this->oDB->connection, $sSQL);
|
||||
echo "Latest data imported from $sDatabaseDate.\n";
|
||||
}
|
||||
}
|
||||
@@ -495,12 +477,7 @@ class SetupFunctions
|
||||
|
||||
$aDBInstances = array();
|
||||
for ($i = 0; $i < $this->iInstances; $i++) {
|
||||
// https://secure.php.net/manual/en/function.pg-connect.php
|
||||
$DSN = CONST_Database_DSN;
|
||||
$DSN = preg_replace('/^pgsql:/', '', $DSN);
|
||||
$DSN = preg_replace('/;/', ' ', $DSN);
|
||||
$aDBInstances[$i] = pg_connect($DSN, PGSQL_CONNECT_FORCE_NEW | PGSQL_CONNECT_ASYNC);
|
||||
pg_ping($aDBInstances[$i]);
|
||||
$aDBInstances[$i] =& getDB(true);
|
||||
}
|
||||
|
||||
foreach (glob(CONST_Tiger_Data_Path.'/*.sql') as $sFile) {
|
||||
@@ -510,11 +487,11 @@ class SetupFunctions
|
||||
$iLines = 0;
|
||||
while (true) {
|
||||
for ($i = 0; $i < $this->iInstances; $i++) {
|
||||
if (!pg_connection_busy($aDBInstances[$i])) {
|
||||
while (pg_get_result($aDBInstances[$i]));
|
||||
if (!pg_connection_busy($aDBInstances[$i]->connection)) {
|
||||
while (pg_get_result($aDBInstances[$i]->connection));
|
||||
$sSQL = fgets($hFile, 100000);
|
||||
if (!$sSQL) break 2;
|
||||
if (!pg_send_query($aDBInstances[$i], $sSQL)) fail(pg_last_error($aDBInstances[$i]));
|
||||
if (!pg_send_query($aDBInstances[$i]->connection, $sSQL)) fail(pg_last_error($this->oDB->connection));
|
||||
$iLines++;
|
||||
if ($iLines == 1000) {
|
||||
echo '.';
|
||||
@@ -530,17 +507,13 @@ class SetupFunctions
|
||||
while ($bAnyBusy) {
|
||||
$bAnyBusy = false;
|
||||
for ($i = 0; $i < $this->iInstances; $i++) {
|
||||
if (pg_connection_busy($aDBInstances[$i])) $bAnyBusy = true;
|
||||
if (pg_connection_busy($aDBInstances[$i]->connection)) $bAnyBusy = true;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $this->iInstances; $i++) {
|
||||
pg_close($aDBInstances[$i]);
|
||||
}
|
||||
|
||||
info('Creating indexes on Tiger data');
|
||||
$sTemplate = file_get_contents(CONST_BasePath.'/sql/tiger_import_finish.sql');
|
||||
$sTemplate = str_replace('{www-user}', CONST_Database_Web_User, $sTemplate);
|
||||
@@ -724,7 +697,7 @@ class SetupFunctions
|
||||
);
|
||||
|
||||
$aDropTables = array();
|
||||
$aHaveTables = $this->oDB->getCol("SELECT tablename FROM pg_tables WHERE schemaname='public'");
|
||||
$aHaveTables = chksql($this->oDB->getCol("SELECT tablename FROM pg_tables WHERE schemaname='public'"));
|
||||
|
||||
foreach ($aHaveTables as $sTable) {
|
||||
$bFound = false;
|
||||
@@ -738,7 +711,7 @@ class SetupFunctions
|
||||
}
|
||||
foreach ($aDropTables as $sDrop) {
|
||||
if ($this->bVerbose) echo "Dropping table $sDrop\n";
|
||||
$this->oDB->exec("DROP TABLE $sDrop CASCADE");
|
||||
@pg_query($this->oDB->connection, "DROP TABLE $sDrop CASCADE");
|
||||
// ignore warnings/errors as they might be caused by a table having
|
||||
// been deleted already by CASCADE
|
||||
}
|
||||
@@ -753,10 +726,7 @@ class SetupFunctions
|
||||
|
||||
private function pgsqlRunDropAndRestore($sDumpFile)
|
||||
{
|
||||
$sCMD = 'pg_restore -p '.$this->aDSNInfo['port'].' -d '.$this->aDSNInfo['database'].' --no-owner -Fc --clean '.$sDumpFile;
|
||||
if ($this->oDB->getPostgresVersion() >= 9.04) {
|
||||
$sCMD .= ' --if-exists';
|
||||
}
|
||||
$sCMD = 'pg_restore -p '.$this->aDSNInfo['port'].' -d '.$this->aDSNInfo['database'].' -Fc --clean '.$sDumpFile;
|
||||
if (isset($this->aDSNInfo['hostspec'])) {
|
||||
$sCMD .= ' -h '.$this->aDSNInfo['hostspec'];
|
||||
}
|
||||
@@ -806,7 +776,7 @@ class SetupFunctions
|
||||
private function pgsqlRunPartitionScript($sTemplate)
|
||||
{
|
||||
$sSQL = 'select distinct partition from country_name';
|
||||
$aPartitions = $this->oDB->getCol($sSQL);
|
||||
$aPartitions = chksql($this->oDB->getCol($sSQL));
|
||||
if (!$this->bNoPartitions) $aPartitions[] = 0;
|
||||
|
||||
preg_match_all('#^-- start(.*?)^-- end#ms', $sTemplate, $aMatches, PREG_SET_ORDER);
|
||||
@@ -913,7 +883,9 @@ class SetupFunctions
|
||||
*/
|
||||
private function pgExec($sSQL)
|
||||
{
|
||||
$this->oDB->exec($sSQL);
|
||||
if (!pg_query($this->oDB->connection, $sSQL)) {
|
||||
fail(pg_last_error($this->oDB->connection));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -923,6 +895,7 @@ class SetupFunctions
|
||||
*/
|
||||
private function dbReverseOnly()
|
||||
{
|
||||
return !($this->oDB->tableExists('search_name'));
|
||||
$sSQL = "SELECT count(*) FROM pg_tables WHERE tablename = 'search_name'";
|
||||
return !(chksql($this->oDB->getOne($sSQL)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,22 @@ function checkInFile($sOSMFile)
|
||||
|
||||
function checkModulePresence()
|
||||
{
|
||||
// Try accessing the C module, so we know early if something is wrong.
|
||||
// Raises Nominatim\DatabaseError on failure
|
||||
|
||||
// Try accessing the C module, so we know early if something is wrong
|
||||
// and can simply error out.
|
||||
$sModulePath = CONST_Database_Module_Path;
|
||||
$sSQL = "CREATE FUNCTION nominatim_test_import_func(text) RETURNS text AS '";
|
||||
$sSQL .= $sModulePath . "/nominatim.so', 'transliteration' LANGUAGE c IMMUTABLE STRICT";
|
||||
$sSQL .= ';DROP FUNCTION nominatim_test_import_func(text);';
|
||||
|
||||
$oDB = new \Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB->exec($sSQL, null, 'Database server failed to load '.$sModulePath.'/nominatim.so module');
|
||||
$oDB = &getDB();
|
||||
$oResult = $oDB->query($sSQL);
|
||||
|
||||
$bResult = true;
|
||||
|
||||
if (PEAR::isError($oResult)) {
|
||||
echo "\nERROR: Failed to load nominatim module. Reason:\n";
|
||||
echo $oResult->userinfo . "\n\n";
|
||||
$bResult = false;
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
|
||||
function _one_row($aAddressLine){
|
||||
$bNotUsed = isset($aAddressLine['isaddress']) && !$aAddressLine['isaddress'];
|
||||
$bNotUsed = (isset($aAddressLine['isaddress']) && $aAddressLine['isaddress'] == 'f');
|
||||
|
||||
echo '<tr class="' . ($bNotUsed?'notused':'') . '">'."\n";
|
||||
echo ' <td class="name">'.(trim($aAddressLine['localname'])?$aAddressLine['localname']:'<span class="noname">No Name</span>')."</td>\n";
|
||||
@@ -119,7 +119,7 @@
|
||||
if ($aPointDetails['calculated_importance']) {
|
||||
kv('Importance' , $aPointDetails['calculated_importance'].($aPointDetails['importance']?'':' (estimated)') );
|
||||
}
|
||||
kv('Coverage' , ($aPointDetails['isarea']?'Polygon':'Point') );
|
||||
kv('Coverage' , ($aPointDetails['isarea']=='t'?'Polygon':'Point') );
|
||||
kv('Centre Point' , $aPointDetails['lat'].','.$aPointDetails['lon'] );
|
||||
kv('OSM' , osmLink($aPointDetails) );
|
||||
if ($aPointDetails['wikipedia'])
|
||||
|
||||
@@ -33,7 +33,7 @@ if ($aPointDetails['icon']) {
|
||||
$aPlaceDetails['rank_address'] = (int) $aPointDetails['rank_address'];
|
||||
$aPlaceDetails['rank_search'] = (int) $aPointDetails['rank_search'];
|
||||
|
||||
$aPlaceDetails['isarea'] = $aPointDetails['isarea'];
|
||||
$aPlaceDetails['isarea'] = ($aPointDetails['isarea'] == 't');
|
||||
$aPlaceDetails['centroid'] = array(
|
||||
'type' => 'Point',
|
||||
'coordinates' => array( (float) $aPointDetails['lon'], (float) $aPointDetails['lat'] )
|
||||
|
||||
@@ -7,7 +7,7 @@ if (isset($_GET['debug']) && $_GET['debug']) @define('CONST_Debug', true);
|
||||
|
||||
// General settings
|
||||
@define('CONST_Debug', false);
|
||||
@define('CONST_Database_DSN', 'pgsql:dbname=nominatim'); // or add ;host=...;port=...;user=...;password=...
|
||||
@define('CONST_Database_DSN', 'pgsql://@/nominatim'); // <driver>://<username>:<password>@<host>:<port>/<database>
|
||||
@define('CONST_Database_Web_User', 'www-data');
|
||||
@define('CONST_Database_Module_Path', CONST_InstallPath.'/module');
|
||||
@define('CONST_Max_Word_Frequency', '50000');
|
||||
|
||||
@@ -2318,7 +2318,6 @@ DECLARE
|
||||
searchhousename HSTORE;
|
||||
searchrankaddress INTEGER;
|
||||
searchpostcode TEXT;
|
||||
postcode_isaddress BOOL;
|
||||
searchclass TEXT;
|
||||
searchtype TEXT;
|
||||
countryname HSTORE;
|
||||
@@ -2326,8 +2325,6 @@ BEGIN
|
||||
-- The place ein question might not have a direct entry in place_addressline.
|
||||
-- Look for the parent of such places then and save if in for_place_id.
|
||||
|
||||
postcode_isaddress := true;
|
||||
|
||||
-- first query osmline (interpolation lines)
|
||||
IF in_housenumber >= 0 THEN
|
||||
SELECT parent_place_id, country_code, in_housenumber::text, 30, postcode,
|
||||
@@ -2444,10 +2441,7 @@ BEGIN
|
||||
searchcountrycode := location.country_code;
|
||||
END IF;
|
||||
IF location.type in ('postcode', 'postal_code') THEN
|
||||
postcode_isaddress := false;
|
||||
IF location.osm_type != 'R' THEN
|
||||
location.isaddress := FALSE;
|
||||
END IF;
|
||||
location.isaddress := FALSE;
|
||||
END IF;
|
||||
countrylocation := ROW(location.place_id, location.osm_type, location.osm_id,
|
||||
location.name, location.class, location.type,
|
||||
@@ -2491,7 +2485,7 @@ BEGIN
|
||||
|
||||
IF searchpostcode IS NOT NULL THEN
|
||||
location := ROW(null, null, null, hstore('ref', searchpostcode), 'place',
|
||||
'postcode', null, false, postcode_isaddress, 5, 0)::addressline;
|
||||
'postcode', null, true, true, 5, 0)::addressline;
|
||||
RETURN NEXT location;
|
||||
END IF;
|
||||
|
||||
|
||||
@@ -34,10 +34,3 @@ Feature: Object details
|
||||
| 1 |
|
||||
Then the result is valid html
|
||||
|
||||
# ticket #1343
|
||||
Scenario: Details of a country with keywords
|
||||
When sending details query for R287072
|
||||
| keywords |
|
||||
| 1 |
|
||||
Then the result is valid html
|
||||
|
||||
|
||||
@@ -26,18 +26,6 @@ Feature: Searches with postcodes
|
||||
| country_code |
|
||||
| li |
|
||||
|
||||
Scenario: Postcode search with bounded viewbox restriction
|
||||
When sending json search query "9486" with address
|
||||
| bounded | viewbox |
|
||||
| 1 | 9.55,47.20,9.58,47.22 |
|
||||
Then result addresses contain
|
||||
| postcode |
|
||||
| 9486 |
|
||||
When sending json search query "9486" with address
|
||||
| bounded | viewbox |
|
||||
| 1 | 5.00,20.00,6.00,21.00 |
|
||||
Then exactly 0 results are returned
|
||||
|
||||
Scenario: Postcode search with structured query
|
||||
When sending json search query "" with address
|
||||
| postalcode | country |
|
||||
|
||||
@@ -5,7 +5,7 @@ Feature: Status queries against unknown database
|
||||
Scenario: Failed status as text
|
||||
When sending text status query
|
||||
Then a HTTP 500 is returned
|
||||
And the page contents equals "ERROR: Database connection failed"
|
||||
And the page contents equals "ERROR: No database"
|
||||
|
||||
Scenario: Failed status as json
|
||||
When sending json status query
|
||||
@@ -13,5 +13,5 @@ Feature: Status queries against unknown database
|
||||
And the result is valid json
|
||||
And results contain
|
||||
| status | message |
|
||||
| 700 | Database connection failed |
|
||||
| 700 | No database |
|
||||
And result has not attributes data_updated
|
||||
|
||||
@@ -344,23 +344,3 @@ Feature: Import of address interpolations
|
||||
When importing
|
||||
Then W1 expands to no interpolation
|
||||
|
||||
Scenario: Two point interpolation starting at 0
|
||||
Given the places
|
||||
| osm | class | type | housenr | geometry |
|
||||
| N1 | place | house | 0 | 1 1 |
|
||||
| N2 | place | house | 2 | 1 1.001 |
|
||||
And the places
|
||||
| osm | class | type | addr+interpolation | geometry |
|
||||
| W1 | place | houses | even | 1 1, 1 1.001 |
|
||||
And the ways
|
||||
| id | nodes |
|
||||
| 1 | 1,2 |
|
||||
When importing
|
||||
Then W1 expands to interpolation
|
||||
| start | end | geometry |
|
||||
| 0 | 2 | 1 1, 1 1.001 |
|
||||
When sending jsonv2 reverse coordinates 1,1
|
||||
Then results contain
|
||||
| ID | osm_type | osm_id | type | display_name |
|
||||
| 0 | way | 1 | house | 0 |
|
||||
|
||||
|
||||
@@ -73,14 +73,12 @@ class NominatimEnvironment(object):
|
||||
|
||||
def write_nominatim_config(self, dbname):
|
||||
f = open(self.local_settings_file, 'w')
|
||||
# https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
|
||||
f.write("<?php\n @define('CONST_Database_DSN', 'pgsql:dbname=%s%s%s%s%s');\n" %
|
||||
(dbname,
|
||||
(';host=' + self.db_host) if self.db_host else '',
|
||||
(';port=' + self.db_port) if self.db_port else '',
|
||||
(';user=' + self.db_user) if self.db_user else '',
|
||||
(';password=' + self.db_pass) if self.db_pass else ''
|
||||
))
|
||||
f.write("<?php\n @define('CONST_Database_DSN', 'pgsql://%s:%s@%s%s/%s');\n" %
|
||||
(self.db_user if self.db_user else '',
|
||||
self.db_pass if self.db_pass else '',
|
||||
self.db_host if self.db_host else '',
|
||||
(':' + self.db_port) if self.db_port else '',
|
||||
dbname))
|
||||
f.write("@define('CONST_Osm2pgsql_Flatnode_File', null);\n")
|
||||
f.close()
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ class GenericResponse(object):
|
||||
pass
|
||||
elif h == 'osm':
|
||||
assert_equal(res['osm_type'], row[h][0])
|
||||
assert_equal(res['osm_id'], int(row[h][1:]))
|
||||
assert_equal(res['osm_id'], row[h][1:])
|
||||
elif h == 'centroid':
|
||||
x, y = row[h].split(' ')
|
||||
assert_almost_equal(float(y), float(res['lat']))
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Nominatim;
|
||||
|
||||
require_once(CONST_BasePath.'/lib/lib.php');
|
||||
require_once(CONST_BasePath.'/lib/DB.php');
|
||||
|
||||
// subclassing so we can set the protected connection variable
|
||||
class NominatimSubClassedDB extends \Nominatim\DB
|
||||
{
|
||||
public function setConnection($oConnection)
|
||||
{
|
||||
$this->connection = $oConnection;
|
||||
}
|
||||
}
|
||||
|
||||
// phpcs:ignore PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
class DBTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testReusingConnection()
|
||||
{
|
||||
$oDB = new NominatimSubClassedDB('');
|
||||
$oDB->setConnection('anything');
|
||||
$this->assertTrue($oDB->connect());
|
||||
}
|
||||
|
||||
public function testDatabaseExists()
|
||||
{
|
||||
$oDB = new \Nominatim\DB('');
|
||||
$this->assertFalse($oDB->databaseExists());
|
||||
}
|
||||
|
||||
public function testErrorHandling()
|
||||
{
|
||||
$this->expectException(DatabaseError::class);
|
||||
$this->expectExceptionMessage('Failed to establish database connection');
|
||||
|
||||
$oDB = new \Nominatim\DB('pgsql:dbname=abc');
|
||||
$oDB->connect();
|
||||
}
|
||||
|
||||
public function testErrorHandling2()
|
||||
{
|
||||
$this->expectException(DatabaseError::class);
|
||||
$this->expectExceptionMessage('Database query failed');
|
||||
|
||||
$oPDOStub = $this->getMockBuilder(PDO::class)
|
||||
->setMethods(array('query', 'quote'))
|
||||
->getMock();
|
||||
|
||||
$oPDOStub->method('query')
|
||||
->will($this->returnCallback(function ($sVal) {
|
||||
return "'$sVal'";
|
||||
}));
|
||||
|
||||
$oPDOStub->method('query')
|
||||
->will($this->returnCallback(function () {
|
||||
throw new \PDOException('ERROR: syntax error at or near "FROM"');
|
||||
}));
|
||||
|
||||
$oDB = new NominatimSubClassedDB('');
|
||||
$oDB->setConnection($oPDOStub);
|
||||
$oDB->getOne('SELECT name FROM');
|
||||
}
|
||||
|
||||
public function testGetPostgresVersion()
|
||||
{
|
||||
$oDBStub = $this->getMockBuilder(\Nominatim\DB::class)
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('getOne'))
|
||||
->getMock();
|
||||
|
||||
$oDBStub->method('getOne')
|
||||
->willReturn('100006');
|
||||
|
||||
$this->assertEquals(10, $oDBStub->getPostgresVersion());
|
||||
}
|
||||
|
||||
public function testGetPostgisVersion()
|
||||
{
|
||||
$oDBStub = $this->getMockBuilder(\Nominatim\DB::class)
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('getOne'))
|
||||
->getMock();
|
||||
|
||||
$oDBStub->method('getOne')
|
||||
->willReturn('2.4.4');
|
||||
|
||||
$this->assertEquals(2.4, $oDBStub->getPostgisVersion());
|
||||
}
|
||||
|
||||
public function testParseDSN()
|
||||
{
|
||||
$this->assertEquals(
|
||||
array(),
|
||||
\Nominatim\DB::parseDSN('')
|
||||
);
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'database' => 'db1',
|
||||
'hostspec' => 'machine1'
|
||||
),
|
||||
\Nominatim\DB::parseDSN('pgsql:dbname=db1;host=machine1')
|
||||
);
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'database' => 'db1',
|
||||
'hostspec' => 'machine1',
|
||||
'port' => '1234',
|
||||
'username' => 'john',
|
||||
'password' => 'secret'
|
||||
),
|
||||
\Nominatim\DB::parseDSN('pgsql:dbname=db1;host=machine1;port=1234;user=john;password=secret')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ class DatabaseErrorTest extends \PHPUnit\Framework\TestCase
|
||||
|
||||
public function testSqlMessage()
|
||||
{
|
||||
$oSqlStub = $this->getMockBuilder(PDOException::class)
|
||||
$oSqlStub = $this->getMockBuilder(\DB_Error::class)
|
||||
->setMethods(array('getMessage'))
|
||||
->getMock();
|
||||
|
||||
@@ -21,6 +21,9 @@ class DatabaseErrorTest extends \PHPUnit\Framework\TestCase
|
||||
$this->assertEquals('Sql error', $oErr->getMessage());
|
||||
$this->assertEquals(123, $oErr->getCode());
|
||||
$this->assertEquals('Unknown table.', $oErr->getSqlError());
|
||||
|
||||
// causes a circular reference warning during dump
|
||||
// $this->assertRegExp('/Mock_DB_Error/', $oErr->getSqlDebugDump());
|
||||
}
|
||||
|
||||
public function testSqlObjectDump()
|
||||
@@ -28,4 +31,14 @@ class DatabaseErrorTest extends \PHPUnit\Framework\TestCase
|
||||
$oErr = new DatabaseError('Sql error', 123, null, array('one' => 'two'));
|
||||
$this->assertRegExp('/two/', $oErr->getSqlDebugDump());
|
||||
}
|
||||
|
||||
public function testChksqlThrows()
|
||||
{
|
||||
$this->expectException(DatabaseError::class);
|
||||
$this->expectExceptionMessage('My custom error message');
|
||||
$this->expectExceptionCode(500);
|
||||
|
||||
$oDB = new \DB_Error;
|
||||
$this->assertEquals(false, chksql($oDB, 'My custom error message'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Nominatim;
|
||||
|
||||
require_once(CONST_BasePath.'/lib/DB.php');
|
||||
require_once(CONST_BasePath.'/lib/db.php');
|
||||
require_once(CONST_BasePath.'/lib/Status.php');
|
||||
|
||||
|
||||
@@ -23,20 +23,19 @@ class StatusTest extends \PHPUnit\Framework\TestCase
|
||||
public function testNoDatabaseConnectionFail()
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage('Database connection failed');
|
||||
$this->expectExceptionMessage('No database');
|
||||
$this->expectExceptionCode(700);
|
||||
|
||||
$oDbStub = $this->getMockBuilder(Nominatim\DB::class)
|
||||
->setMethods(array('connect'))
|
||||
->getMock();
|
||||
// causes 'Non-static method should not be called statically, assuming $this from incompatible context'
|
||||
// failure on travis
|
||||
// $oDB = \DB::connect('', false); // returns a DB_Error instance
|
||||
|
||||
$oDbStub->method('connect')
|
||||
->will($this->returnCallback(function () {
|
||||
throw new \Nominatim\DatabaseError('psql connection problem', 500, null, 'unknown database');
|
||||
}));
|
||||
$oDB = new \DB_Error;
|
||||
$oStatus = new Status($oDB);
|
||||
$this->assertEquals('No database', $oStatus->status());
|
||||
|
||||
|
||||
$oStatus = new Status($oDbStub);
|
||||
$oDB = null;
|
||||
$oStatus = new Status($oDB);
|
||||
$this->assertEquals('No database', $oStatus->status());
|
||||
}
|
||||
|
||||
@@ -48,8 +47,8 @@ class StatusTest extends \PHPUnit\Framework\TestCase
|
||||
$this->expectExceptionCode(702);
|
||||
|
||||
// stub has getOne method but doesn't return anything
|
||||
$oDbStub = $this->getMockBuilder(Nominatim\DB::class)
|
||||
->setMethods(array('connect', 'getOne'))
|
||||
$oDbStub = $this->getMockBuilder(\DB::class)
|
||||
->setMethods(array('getOne'))
|
||||
->getMock();
|
||||
|
||||
$oStatus = new Status($oDbStub);
|
||||
@@ -63,8 +62,8 @@ class StatusTest extends \PHPUnit\Framework\TestCase
|
||||
$this->expectExceptionMessage('No value');
|
||||
$this->expectExceptionCode(704);
|
||||
|
||||
$oDbStub = $this->getMockBuilder(Nominatim\DB::class)
|
||||
->setMethods(array('connect', 'getOne'))
|
||||
$oDbStub = $this->getMockBuilder(\DB::class)
|
||||
->setMethods(array('getOne'))
|
||||
->getMock();
|
||||
|
||||
// return no word_id
|
||||
@@ -81,8 +80,8 @@ class StatusTest extends \PHPUnit\Framework\TestCase
|
||||
|
||||
public function testOK()
|
||||
{
|
||||
$oDbStub = $this->getMockBuilder(Nominatim\DB::class)
|
||||
->setMethods(array('connect', 'getOne'))
|
||||
$oDbStub = $this->getMockBuilder(\DB::class)
|
||||
->setMethods(array('getOne'))
|
||||
->getMock();
|
||||
|
||||
$oDbStub->method('getOne')
|
||||
@@ -97,7 +96,7 @@ class StatusTest extends \PHPUnit\Framework\TestCase
|
||||
|
||||
public function testDataDate()
|
||||
{
|
||||
$oDbStub = $this->getMockBuilder(Nominatim\DB::class)
|
||||
$oDbStub = $this->getMockBuilder(\DB::class)
|
||||
->setMethods(array('getOne'))
|
||||
->getMock();
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Nominatim;
|
||||
|
||||
// require_once(CONST_BasePath.'/lib/db.php');
|
||||
// require_once(CONST_BasePath.'/lib/cmd.php');
|
||||
require_once(CONST_BasePath.'/lib/TokenList.php');
|
||||
|
||||
|
||||
@@ -54,18 +56,9 @@ class TokenTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
$this->expectOutputRegex('/<p><tt>/');
|
||||
|
||||
$oDbStub = $this->getMockBuilder(Nominatim\DB::class)
|
||||
->setMethods(array('getAll', 'getDBQuotedList'))
|
||||
$oDbStub = $this->getMockBuilder(\DB::class)
|
||||
->setMethods(array('getAll'))
|
||||
->getMock();
|
||||
|
||||
$oDbStub->method('getDBQuotedList')
|
||||
->will($this->returnCallback(function ($aVals) {
|
||||
return array_map(function ($sVal) {
|
||||
return "'".$sVal."'";
|
||||
}, $aVals);
|
||||
}));
|
||||
|
||||
|
||||
$oDbStub->method('getAll')
|
||||
->will($this->returnCallback(function ($sql) {
|
||||
$aResults = array();
|
||||
|
||||
@@ -41,8 +41,7 @@
|
||||
'path' => 27
|
||||
);
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB =& getDB();
|
||||
|
||||
if (isset($aCMDResult['output-type'])) {
|
||||
if (!isset($aRankmap[$aCMDResult['output-type']])) fail('unknown output-type: '.$aCMDResult['output-type']);
|
||||
@@ -56,7 +55,7 @@
|
||||
$oParams = new Nominatim\ParameterParser();
|
||||
if (!isset($aCMDResult['language'])) $aCMDResult['language'] = 'xx';
|
||||
$aLangPrefOrder = $oParams->getPreferredLanguages($aCMDResult['language']);
|
||||
$sLanguagePrefArraySQL = $oDB->getArraySQL($oDB->getDBQuotedList($aLangPrefOrder));
|
||||
$sLanguagePrefArraySQL = 'ARRAY['.join(',', array_map('getDBQuoted', $aLangPrefOrder)).']';
|
||||
|
||||
// output formatting: build up a lookup table that maps address ranks to columns
|
||||
$aColumnMapping = array();
|
||||
@@ -96,7 +95,7 @@
|
||||
$sPlacexSQL .= ' and rank_address = '.$iOutputRank;
|
||||
|
||||
if (isset($aCMDResult['restrict-to-country'])) {
|
||||
$sPlacexSQL .= ' and country_code = '.$oDB->getDBQuoted($aCMDResult['restrict-to-country']);
|
||||
$sPlacexSQL .= ' and country_code = '.getDBQuoted($aCMDResult['restrict-to-country']);
|
||||
}
|
||||
|
||||
// restriction to parent place id
|
||||
@@ -116,8 +115,11 @@
|
||||
$sOsmId = $aCMDResult['restrict-to-osm-relation'];
|
||||
}
|
||||
if ($sOsmType) {
|
||||
$sSQL = 'select place_id from placex where osm_type = :osm_type and osm_id = :osm_id';
|
||||
$sParentId = $oDB->getOne($sSQL, array('osm_type' => $sOsmType, 'osm_id' => $sOsmId));
|
||||
$sSQL = 'select place_id from placex where';
|
||||
$sSQL .= ' osm_type = '.getDBQuoted($sOsmType);
|
||||
$sSQL .= ' and osm_id = '.$sOsmId;
|
||||
$sParentId = $oDB->getOne($sSQL);
|
||||
if (PEAR::isError($sParentId)) fail(pg_last_error($oDB->connection));
|
||||
if (!$sParentId) fail('Could not find place '.$sOsmType.' '.$sOsmId);
|
||||
}
|
||||
if ($sParentId) {
|
||||
@@ -129,15 +131,18 @@
|
||||
// Iterate over placeids
|
||||
// to get further hierarchical information
|
||||
//var_dump($sPlacexSQL);
|
||||
$oResults = $oDB->getQueryStatement($sPlacexSQL);
|
||||
$aRes =& $oDB->query($sPlacexSQL);
|
||||
if (PEAR::isError($aRes)) fail(pg_last_error($oDB->connection));
|
||||
$fOutstream = fopen('php://output', 'w');
|
||||
while ($aRow = $oResults->fetch()) {
|
||||
//var_dump($aRow);
|
||||
while ($aRes->fetchInto($aRow)) {
|
||||
//var_dump($aRow);
|
||||
$iPlaceID = $aRow['place_id'];
|
||||
$sSQL = "select rank_address,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata(:place_id, -1)";
|
||||
$sSQL = "select rank_address,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata($iPlaceID, -1)";
|
||||
$sSQL .= ' WHERE isaddress';
|
||||
$sSQL .= ' order by rank_address desc,isaddress desc';
|
||||
$aAddressLines = $oDB->getAll($sSQL, array('place_id' => $iPlaceID));
|
||||
$aAddressLines = $oDB->getAll($sSQL);
|
||||
if (PEAR::IsError($aAddressLines)) fail(pg_last_error($oDB->connection));
|
||||
|
||||
|
||||
$aOutput = array_fill(0, $iNumCol, '');
|
||||
// output address parts
|
||||
@@ -152,10 +157,10 @@
|
||||
$sSQL = 'select array_agg(px.postcode) from placex px join place_addressline pa ';
|
||||
$sSQL .= 'on px.place_id = pa.address_place_id ';
|
||||
$sSQL .= 'where pa.cached_rank_address in (5,11) ';
|
||||
$sSQL .= 'and pa.place_id in (select place_id from place_addressline where address_place_id in (:first_place_id)) ';
|
||||
$sSQL .= 'and pa.place_id in (select place_id from place_addressline where address_place_id in ('.substr($aRow['place_ids'], 1, -1).')) ';
|
||||
$sSQL .= 'group by postcode order by count(*) desc limit 1';
|
||||
$sRes = $oDB->getOne($sSQL, array('first_place_id' => substr($aRow['place_ids'], 1, -1)));
|
||||
|
||||
$sRes = $oDB->getOne($sSQL);
|
||||
if (PEAR::IsError($sRes)) fail(pg_last_error($oDB->connection));
|
||||
$aOutput[$aColumnMapping['postcode']] = substr($sRes, 1, -1);
|
||||
} else {
|
||||
$aOutput[$aColumnMapping['postcode']] = $aRow['postcode'];
|
||||
|
||||
@@ -48,8 +48,7 @@ exit;
|
||||
$a = array();
|
||||
$a[] = 'test';
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB &= getDB();
|
||||
|
||||
if ($aCMDResult['drop-tables'])
|
||||
{
|
||||
@@ -305,9 +304,7 @@ function _templatesToProperties($aTemplates)
|
||||
}
|
||||
|
||||
if (isset($aCMDResult['parse-wikipedia'])) {
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
|
||||
$oDB =& getDB();
|
||||
$sSQL = 'select page_title from content where page_namespace = 0 and page_id %10 = ';
|
||||
$sSQL .= $aCMDResult['parse-wikipedia'];
|
||||
$sSQL .= ' and (page_content ilike \'%{{Coord%\' or (page_content ilike \'%lat%\' and page_content ilike \'%lon%\'))';
|
||||
@@ -369,9 +366,7 @@ function nominatimXMLEnd($hParser, $sName)
|
||||
|
||||
|
||||
if (isset($aCMDResult['link'])) {
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
|
||||
$oDB =& getDB();
|
||||
$aWikiArticles = $oDB->getAll("select * from wikipedia_article where language = 'en' and lat is not null and osm_type is null and totalcount < 31 order by importance desc limit 200000");
|
||||
|
||||
// If you point this script at production OSM you will be blocked
|
||||
|
||||
@@ -25,9 +25,7 @@ $aCMDOptions
|
||||
);
|
||||
getCmdOpt($_SERVER['argv'], $aCMDOptions, $aCMDResult, true, true);
|
||||
|
||||
$oDB = new Nominatim\DB;
|
||||
$oDB->connect();
|
||||
|
||||
$oDB =& getDB();
|
||||
$oParams = new Nominatim\ParameterParser($aCMDResult);
|
||||
|
||||
if ($oParams->getBool('search')) {
|
||||
|
||||
@@ -84,7 +84,9 @@ if ($aCMDResult['setup-db'] || $aCMDResult['all']) {
|
||||
}
|
||||
|
||||
// Try accessing the C module, so we know early if something is wrong
|
||||
checkModulePresence(); // raises exception on failure
|
||||
if (!checkModulePresence()) {
|
||||
fail('error loading nominatim.so module');
|
||||
}
|
||||
|
||||
if ($aCMDResult['import-data'] || $aCMDResult['all']) {
|
||||
$bDidSomething = true;
|
||||
|
||||
@@ -52,10 +52,9 @@ if (!isset($aResult['index-rank'])) $aResult['index-rank'] = 0;
|
||||
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB =& getDB();
|
||||
|
||||
$aDSNInfo = Nominatim\DB::parseDSN(CONST_Database_DSN);
|
||||
$aDSNInfo = DB::parseDSN(CONST_Database_DSN);
|
||||
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
|
||||
|
||||
// cache memory to be used by osm2pgsql, should not be more than the available memory
|
||||
@@ -116,7 +115,7 @@ if ($aResult['init-updates']) {
|
||||
}
|
||||
|
||||
$sDatabaseDate = getDatabaseDate($oDB);
|
||||
if (!$sDatabaseDate) {
|
||||
if ($sDatabaseDate === false) {
|
||||
fail('Cannot determine date of database.');
|
||||
}
|
||||
$sWindBack = strftime('%Y-%m-%dT%H:%M:%SZ', strtotime($sDatabaseDate) - (3*60*60));
|
||||
@@ -129,13 +128,10 @@ if ($aResult['init-updates']) {
|
||||
fail('Error running pyosmium tools');
|
||||
}
|
||||
|
||||
$oDB->exec('TRUNCATE import_status');
|
||||
pg_query($oDB->connection, 'TRUNCATE import_status');
|
||||
$sSQL = "INSERT INTO import_status (lastimportdate, sequence_id, indexed) VALUES('";
|
||||
$sSQL .= $sDatabaseDate."',".$aOutput[0].', true)';
|
||||
|
||||
try {
|
||||
$oDB->exec($sSQL);
|
||||
} catch (\Nominatim\DatabaseError $e) {
|
||||
if (!pg_query($oDB->connection, $sSQL)) {
|
||||
fail('Could not enter sequence into database.');
|
||||
}
|
||||
|
||||
@@ -143,7 +139,7 @@ if ($aResult['init-updates']) {
|
||||
}
|
||||
|
||||
if ($aResult['check-for-updates']) {
|
||||
$aLastState = $oDB->getRow('SELECT sequence_id FROM import_status');
|
||||
$aLastState = chksql($oDB->getRow('SELECT sequence_id FROM import_status'));
|
||||
|
||||
if (!$aLastState['sequence_id']) {
|
||||
fail('Updates not set up. Please run ./utils/update.php --init-updates.');
|
||||
@@ -223,21 +219,20 @@ if ($bHaveDiff) {
|
||||
}
|
||||
|
||||
if ($aResult['deduplicate']) {
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB =& getDB();
|
||||
|
||||
if ($oDB->getPostgresVersion() < 9.3) {
|
||||
if (getPostgresVersion($oDB) < 9.3) {
|
||||
fail('ERROR: deduplicate is only currently supported in postgresql 9.3');
|
||||
}
|
||||
|
||||
$sSQL = 'select partition from country_name order by country_code';
|
||||
$aPartitions = $oDB->getCol($sSQL);
|
||||
$aPartitions = chksql($oDB->getCol($sSQL));
|
||||
$aPartitions[] = 0;
|
||||
|
||||
// we don't care about empty search_name_* partitions, they can't contain mentions of duplicates
|
||||
foreach ($aPartitions as $i => $sPartition) {
|
||||
$sSQL = 'select count(*) from search_name_'.$sPartition;
|
||||
$nEntries = $oDB->getOne($sSQL);
|
||||
$nEntries = chksql($oDB->getOne($sSQL));
|
||||
if ($nEntries == 0) {
|
||||
unset($aPartitions[$i]);
|
||||
}
|
||||
@@ -246,7 +241,7 @@ if ($aResult['deduplicate']) {
|
||||
$sSQL = "select word_token,count(*) from word where substr(word_token, 1, 1) = ' '";
|
||||
$sSQL .= ' and class is null and type is null and country_code is null';
|
||||
$sSQL .= ' group by word_token having count(*) > 1 order by word_token';
|
||||
$aDuplicateTokens = $oDB->getAll($sSQL);
|
||||
$aDuplicateTokens = chksql($oDB->getAll($sSQL));
|
||||
foreach ($aDuplicateTokens as $aToken) {
|
||||
if (trim($aToken['word_token']) == '' || trim($aToken['word_token']) == '-') continue;
|
||||
echo 'Deduping '.$aToken['word_token']."\n";
|
||||
@@ -254,7 +249,7 @@ if ($aResult['deduplicate']) {
|
||||
$sSQL .= ' (select count(*) from search_name where nameaddress_vector @> ARRAY[word_id]) as num';
|
||||
$sSQL .= " from word where word_token = '".$aToken['word_token'];
|
||||
$sSQL .= "' and class is null and type is null and country_code is null order by num desc";
|
||||
$aTokenSet = $oDB->getAll($sSQL);
|
||||
$aTokenSet = chksql($oDB->getAll($sSQL));
|
||||
|
||||
$aKeep = array_shift($aTokenSet);
|
||||
$iKeepID = $aKeep['word_id'];
|
||||
@@ -264,32 +259,32 @@ if ($aResult['deduplicate']) {
|
||||
$sSQL .= ' name_vector = array_replace(name_vector,'.$aRemove['word_id'].','.$iKeepID.'),';
|
||||
$sSQL .= ' nameaddress_vector = array_replace(nameaddress_vector,'.$aRemove['word_id'].','.$iKeepID.')';
|
||||
$sSQL .= ' where name_vector @> ARRAY['.$aRemove['word_id'].']';
|
||||
$oDB->exec($sSQL);
|
||||
chksql($oDB->query($sSQL));
|
||||
|
||||
$sSQL = 'update search_name set';
|
||||
$sSQL .= ' nameaddress_vector = array_replace(nameaddress_vector,'.$aRemove['word_id'].','.$iKeepID.')';
|
||||
$sSQL .= ' where nameaddress_vector @> ARRAY['.$aRemove['word_id'].']';
|
||||
$oDB->exec($sSQL);
|
||||
chksql($oDB->query($sSQL));
|
||||
|
||||
$sSQL = 'update location_area_country set';
|
||||
$sSQL .= ' keywords = array_replace(keywords,'.$aRemove['word_id'].','.$iKeepID.')';
|
||||
$sSQL .= ' where keywords @> ARRAY['.$aRemove['word_id'].']';
|
||||
$oDB->exec($sSQL);
|
||||
chksql($oDB->query($sSQL));
|
||||
|
||||
foreach ($aPartitions as $sPartition) {
|
||||
$sSQL = 'update search_name_'.$sPartition.' set';
|
||||
$sSQL .= ' name_vector = array_replace(name_vector,'.$aRemove['word_id'].','.$iKeepID.')';
|
||||
$sSQL .= ' where name_vector @> ARRAY['.$aRemove['word_id'].']';
|
||||
$oDB->exec($sSQL);
|
||||
chksql($oDB->query($sSQL));
|
||||
|
||||
$sSQL = 'update location_area_country set';
|
||||
$sSQL .= ' keywords = array_replace(keywords,'.$aRemove['word_id'].','.$iKeepID.')';
|
||||
$sSQL .= ' where keywords @> ARRAY['.$aRemove['word_id'].']';
|
||||
$oDB->exec($sSQL);
|
||||
chksql($oDB->query($sSQL));
|
||||
}
|
||||
|
||||
$sSQL = 'delete from word where word_id = '.$aRemove['word_id'];
|
||||
$oDB->exec($sSQL);
|
||||
chksql($oDB->query($sSQL));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,7 +306,7 @@ if ($aResult['index']) {
|
||||
|
||||
runWithEnv($sCmd, $aProcEnv);
|
||||
|
||||
$oDB->exec('update import_status set indexed = true');
|
||||
$oDB->query('update import_status set indexed = true');
|
||||
}
|
||||
|
||||
if ($aResult['update-address-levels']) {
|
||||
@@ -340,7 +335,7 @@ if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
|
||||
|
||||
while (true) {
|
||||
$fStartTime = time();
|
||||
$aLastState = $oDB->getRow('SELECT *, EXTRACT (EPOCH FROM lastimportdate) as unix_ts FROM import_status');
|
||||
$aLastState = chksql($oDB->getRow('SELECT *, EXTRACT (EPOCH FROM lastimportdate) as unix_ts FROM import_status'));
|
||||
|
||||
if (!$aLastState['sequence_id']) {
|
||||
echo "Updates not set up. Please run ./utils/update.php --init-updates.\n";
|
||||
@@ -352,7 +347,7 @@ if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
|
||||
$sBatchEnd = $aLastState['lastimportdate'];
|
||||
$iEndSequence = $aLastState['sequence_id'];
|
||||
|
||||
if ($aLastState['indexed']) {
|
||||
if ($aLastState['indexed'] == 't') {
|
||||
// Sleep if the update interval has not yet been reached.
|
||||
$fNextUpdate = $aLastState['unix_ts'] + CONST_Replication_Update_Interval;
|
||||
if ($fNextUpdate > $fStartTime) {
|
||||
@@ -418,12 +413,12 @@ if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
|
||||
$sSQL .= date('Y-m-d H:i:s', $fCMDStartTime)."','";
|
||||
$sSQL .= date('Y-m-d H:i:s')."','import')";
|
||||
var_Dump($sSQL);
|
||||
$oDB->exec($sSQL);
|
||||
chksql($oDB->query($sSQL));
|
||||
|
||||
// update the status
|
||||
$sSQL = "UPDATE import_status SET lastimportdate = '$sBatchEnd', indexed=false, sequence_id = $iEndSequence";
|
||||
var_Dump($sSQL);
|
||||
$oDB->exec($sSQL);
|
||||
chksql($oDB->query($sSQL));
|
||||
echo date('Y-m-d H:i:s')." Completed download step for $sBatchEnd in ".round((time()-$fCMDStartTime)/60, 2)." minutes\n";
|
||||
}
|
||||
|
||||
@@ -445,11 +440,11 @@ if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
|
||||
$sSQL .= date('Y-m-d H:i:s', $fCMDStartTime)."','";
|
||||
$sSQL .= date('Y-m-d H:i:s')."','index')";
|
||||
var_Dump($sSQL);
|
||||
$oDB->exec($sSQL);
|
||||
$oDB->query($sSQL);
|
||||
echo date('Y-m-d H:i:s')." Completed index step for $sBatchEnd in ".round((time()-$fCMDStartTime)/60, 2)." minutes\n";
|
||||
|
||||
$sSQL = 'update import_status set indexed = true';
|
||||
$oDB->exec($sSQL);
|
||||
$oDB->query($sSQL);
|
||||
} else {
|
||||
if ($aResult['import-osmosis-all']) {
|
||||
echo "Error: --no-index cannot be used with continuous imports (--import-osmosis-all).\n";
|
||||
|
||||
@@ -18,8 +18,7 @@ require_once(CONST_BasePath.'/lib/Geocode.php');
|
||||
require_once(CONST_BasePath.'/lib/PlaceLookup.php');
|
||||
require_once(CONST_BasePath.'/lib/ReverseGeocode.php');
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB =& getDB();
|
||||
|
||||
$bVerbose = $aResult['verbose'];
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
sudo yum install -y postgresql-server postgresql-contrib postgresql-devel \
|
||||
postgis postgis-utils \
|
||||
wget git cmake make gcc gcc-c++ libtool policycoreutils-python \
|
||||
php-pgsql php php-intl libpqxx-devel \
|
||||
php-pgsql php php-pear php-pear-DB php-intl libpqxx-devel \
|
||||
proj-epsg bzip2-devel proj-devel libxml2-devel boost-devel \
|
||||
expat-devel zlib-devel
|
||||
|
||||
@@ -34,9 +34,7 @@
|
||||
sudo yum install -y python34-pip python34-setuptools python34-devel \
|
||||
php-phpunit-PHPUnit
|
||||
pip3 install --user behave nose pytidylib psycopg2
|
||||
|
||||
composer global require "squizlabs/php_codesniffer=*"
|
||||
sudo ln -s ~/.config/composer/vendor/bin/phpcs /usr/bin/
|
||||
sudo pear install PHP_CodeSniffer
|
||||
|
||||
#
|
||||
# System Configuration
|
||||
|
||||
@@ -29,7 +29,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
|
||||
libbz2-dev libpq-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 \
|
||||
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
|
||||
@@ -39,9 +39,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
|
||||
python3-psycopg2 python3-tidylib phpunit php-cgi
|
||||
|
||||
pip3 install --user behave nose
|
||||
|
||||
composer global require "squizlabs/php_codesniffer=*"
|
||||
sudo ln -s ~/.config/composer/vendor/bin/phpcs /usr/bin/
|
||||
sudo pear install PHP_CodeSniffer
|
||||
|
||||
#
|
||||
# System Configuration
|
||||
|
||||
@@ -22,7 +22,7 @@ export DEBIAN_FRONTEND=noninteractive
|
||||
libbz2-dev libpq-dev libproj-dev \
|
||||
postgresql-server-dev-10 postgresql-10-postgis-2.4 \
|
||||
postgresql-contrib-10 \
|
||||
nginx php-fpm php php-pgsql \
|
||||
nginx php-fpm php php-pgsql php-pear php-db \
|
||||
php-intl git
|
||||
|
||||
export USERNAME=vagrant
|
||||
|
||||
@@ -29,7 +29,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
|
||||
libbz2-dev libpq-dev libproj-dev \
|
||||
postgresql-server-dev-10 postgresql-10-postgis-2.4 \
|
||||
postgresql-contrib-10 postgresql-10-postgis-scripts \
|
||||
apache2 php php-pgsql libapache2-mod-php \
|
||||
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
|
||||
@@ -39,9 +39,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
|
||||
python3-psycopg2 python3-tidylib phpunit php-cgi
|
||||
|
||||
pip3 install --user behave nose
|
||||
|
||||
composer global require "squizlabs/php_codesniffer=*"
|
||||
sudo ln -s ~/.config/composer/vendor/bin/phpcs /usr/bin/
|
||||
sudo pear install PHP_CodeSniffer
|
||||
|
||||
#
|
||||
# System Configuration
|
||||
|
||||
@@ -16,18 +16,33 @@ sudo apt-get install -y -qq libboost-dev libboost-system-dev \
|
||||
libboost-filesystem-dev libexpat1-dev zlib1g-dev libxml2-dev\
|
||||
libbz2-dev libpq-dev libproj-dev \
|
||||
postgresql-server-dev-9.6 postgresql-9.6-postgis-2.4 postgresql-contrib-9.6 \
|
||||
apache2 php php-pgsql php-intl
|
||||
apache2 php php-pgsql php-intl php-pear
|
||||
|
||||
sudo apt-get install -y -qq python3-dev python3-pip python3-psycopg2 php-cgi
|
||||
|
||||
pip3 install --quiet behave nose pytidylib psycopg2-binary
|
||||
|
||||
# Travis uses phpenv to support multiple PHP versions. We need to make sure
|
||||
# these packages get installed to the phpenv-set PHP (inside /home/travis/.phpenv/),
|
||||
# not the system PHP (/usr/bin/php, /usr/share/php/ etc)
|
||||
|
||||
# $PHPENV_VERSION and $TRAVIS_PHP_VERSION are unset.
|
||||
export PHPENV_VERSION=$(cat /home/travis/.phpenv/version)
|
||||
echo $PHPENV_VERSION
|
||||
|
||||
# https://github.com/pear/DB
|
||||
composer global require "pear/db=1.9.3"
|
||||
# https://github.com/squizlabs/PHP_CodeSniffer
|
||||
composer global require "squizlabs/php_codesniffer=*"
|
||||
sudo ln -s /home/travis/.config/composer/vendor/bin/phpcs /usr/bin/
|
||||
|
||||
composer global require "phpunit/phpunit=7.*"
|
||||
sudo ln -s /home/travis/.config/composer/vendor/bin/phpunit /usr/bin/
|
||||
|
||||
# make sure PEAR.php and DB.php are in the include path
|
||||
tee /tmp/travis.php.ini << EOF
|
||||
include_path = .:/home/travis/.phpenv/versions/$PHPENV_VERSION/share/pear:/home/travis/.config/composer/vendor/pear/db
|
||||
EOF
|
||||
phpenv config-add /tmp/travis.php.ini
|
||||
|
||||
|
||||
sudo -u postgres createuser -S www-data
|
||||
|
||||
@@ -62,7 +77,7 @@ make
|
||||
tee settings/local.php << EOF
|
||||
<?php
|
||||
@define('CONST_Website_BaseURL', '/nominatim/');
|
||||
@define('CONST_Database_DSN', 'pgsql:dbname=test_api_nominatim');
|
||||
@define('CONST_Database_DSN', 'pgsql://@/test_api_nominatim');
|
||||
@define('CONST_Wikipedia_Data_Path', CONST_BasePath.'/test/testdb');
|
||||
EOF
|
||||
|
||||
|
||||
@@ -7,14 +7,13 @@ ini_set('memory_limit', '200M');
|
||||
|
||||
$sOutputFormat = 'html';
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB =& getDB();
|
||||
|
||||
$sSQL = 'select placex.place_id, country_code,';
|
||||
$sSQL .= " name->'name' as name, i.* from placex, import_polygon_delete i";
|
||||
$sSQL .= ' where placex.osm_id = i.osm_id and placex.osm_type = i.osm_type';
|
||||
$sSQL .= ' and placex.class = i.class and placex.type = i.type';
|
||||
$aPolygons = $oDB->getAll($sSQL, null, 'Could not get list of deleted OSM elements.');
|
||||
$aPolygons = chksql($oDB->getAll($sSQL), 'Could not get list of deleted OSM elements.');
|
||||
|
||||
if (CONST_Debug) {
|
||||
var_dump($aPolygons);
|
||||
|
||||
@@ -12,6 +12,7 @@ $sOutputFormat = $oParams->getSet('format', array('html', 'json'), 'html');
|
||||
set_exception_handler_by_format($sOutputFormat);
|
||||
|
||||
$aLangPrefOrder = $oParams->getPreferredLanguages();
|
||||
$sLanguagePrefArraySQL = 'ARRAY['.join(',', array_map('getDBQuoted', $aLangPrefOrder)).']';
|
||||
|
||||
$sPlaceId = $oParams->getString('place_id');
|
||||
$sOsmType = $oParams->getSet('osmtype', array('N', 'W', 'R'));
|
||||
@@ -25,19 +26,20 @@ $bIncludeHierarchy = $oParams->getBool('hierarchy', $sOutputFormat == 'html');
|
||||
$bGroupHierarchy = $oParams->getBool('group_hierarchy', false);
|
||||
$bIncludePolygonAsGeoJSON = $oParams->getBool('polygon_geojson', $sOutputFormat == 'html');
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
|
||||
$sLanguagePrefArraySQL = $oDB->getArraySQL($oDB->getDBQuotedList($aLangPrefOrder));
|
||||
$oDB =& getDB();
|
||||
|
||||
if ($sOsmType && $iOsmId > 0) {
|
||||
$sSQL = 'SELECT place_id FROM placex WHERE osm_type = :type AND osm_id = :id';
|
||||
$sSQL = sprintf(
|
||||
"SELECT place_id FROM placex WHERE osm_type='%s' AND osm_id=%d",
|
||||
$sOsmType,
|
||||
$iOsmId
|
||||
);
|
||||
// osm_type and osm_id are not unique enough
|
||||
if ($sClass) {
|
||||
$sSQL .= " AND class='".$sClass."'";
|
||||
}
|
||||
$sSQL .= ' ORDER BY class ASC';
|
||||
$sPlaceId = $oDB->getOne($sSQL, array(':type' => $sOsmType, ':id' => $iOsmId));
|
||||
$sPlaceId = chksql($oDB->getOne($sSQL));
|
||||
|
||||
// Be nice about our error messages for broken geometry
|
||||
|
||||
@@ -52,12 +54,12 @@ if ($sOsmType && $iOsmId > 0) {
|
||||
$sSQL .= ' ST_AsText(prevgeometry) AS prevgeom, ';
|
||||
$sSQL .= ' ST_AsText(newgeometry) AS newgeom';
|
||||
$sSQL .= ' FROM import_polygon_error ';
|
||||
$sSQL .= ' WHERE osm_type = :type';
|
||||
$sSQL .= ' AND osm_id = :id';
|
||||
$sSQL .= " WHERE osm_type = '".$sOsmType."'";
|
||||
$sSQL .= ' AND osm_id = '.$iOsmId;
|
||||
$sSQL .= ' ORDER BY updated DESC';
|
||||
$sSQL .= ' LIMIT 1';
|
||||
$aPointDetails = $oDB->getRow($sSQL, array(':type' => $sOsmType, ':id' => $iOsmId));
|
||||
if ($aPointDetails) {
|
||||
$aPointDetails = chksql($oDB->getRow($sSQL));
|
||||
if (!PEAR::isError($aPointDetails) && $aPointDetails) {
|
||||
if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches)) {
|
||||
$aPointDetails['error_x'] = $aMatches[1];
|
||||
$aPointDetails['error_y'] = $aMatches[2];
|
||||
@@ -72,25 +74,25 @@ if ($sOsmType && $iOsmId > 0) {
|
||||
}
|
||||
|
||||
|
||||
if ($sPlaceId === false) userError('Please select a place id');
|
||||
if (!$sPlaceId) userError('Please select a place id');
|
||||
|
||||
$iPlaceID = (int)$sPlaceId;
|
||||
|
||||
if (CONST_Use_US_Tiger_Data) {
|
||||
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_tiger WHERE place_id = '.$iPlaceID);
|
||||
$iParentPlaceID = chksql($oDB->getOne('SELECT parent_place_id FROM location_property_tiger WHERE place_id = '.$iPlaceID));
|
||||
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
||||
}
|
||||
|
||||
// interpolated house numbers
|
||||
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_osmline WHERE place_id = '.$iPlaceID);
|
||||
$iParentPlaceID = chksql($oDB->getOne('SELECT parent_place_id FROM location_property_osmline WHERE place_id = '.$iPlaceID));
|
||||
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
||||
|
||||
// artificial postcodes
|
||||
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_postcode WHERE place_id = '.$iPlaceID);
|
||||
$iParentPlaceID = chksql($oDB->getOne('SELECT parent_place_id FROM location_postcode WHERE place_id = '.$iPlaceID));
|
||||
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
||||
|
||||
if (CONST_Use_Aux_Location_data) {
|
||||
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_aux WHERE place_id = '.$iPlaceID);
|
||||
$iParentPlaceID = chksql($oDB->getOne('SELECT parent_place_id FROM location_property_aux WHERE place_id = '.$iPlaceID));
|
||||
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
||||
}
|
||||
|
||||
@@ -125,7 +127,7 @@ if ($bIncludePolygonAsGeoJSON) {
|
||||
$sSQL .= ' FROM placex ';
|
||||
$sSQL .= " WHERE place_id = $iPlaceID";
|
||||
|
||||
$aPointDetails = $oDB->getRow($sSQL, null, 'Could not get details of place object.');
|
||||
$aPointDetails = chksql($oDB->getRow($sSQL), 'Could not get details of place object.');
|
||||
|
||||
if (!$aPointDetails) {
|
||||
userError('Unknown place id.');
|
||||
@@ -139,16 +141,25 @@ $aPointDetails['rank_search_label'] = getSearchRankLabel($aPointDetails['rank_se
|
||||
$sSQL = 'SELECT (each(name)).key,(each(name)).value FROM placex ';
|
||||
$sSQL .= "WHERE place_id = $iPlaceID ORDER BY (each(name)).key";
|
||||
$aPointDetails['aNames'] = $oDB->getAssoc($sSQL);
|
||||
if (PEAR::isError($aPointDetails['aNames'])) { // possible timeout
|
||||
$aPointDetails['aNames'] = array();
|
||||
}
|
||||
|
||||
// Address tags
|
||||
$sSQL = 'SELECT (each(address)).key as key,(each(address)).value FROM placex ';
|
||||
$sSQL .= "WHERE place_id = $iPlaceID ORDER BY key";
|
||||
$aPointDetails['aAddressTags'] = $oDB->getAssoc($sSQL);
|
||||
if (PEAR::isError($aPointDetails['aAddressTags'])) { // possible timeout
|
||||
$aPointDetails['aAddressTags'] = array();
|
||||
}
|
||||
|
||||
// Extra tags
|
||||
$sSQL = 'SELECT (each(extratags)).key,(each(extratags)).value FROM placex ';
|
||||
$sSQL .= "WHERE place_id = $iPlaceID ORDER BY (each(extratags)).key";
|
||||
$aPointDetails['aExtraTags'] = $oDB->getAssoc($sSQL);
|
||||
if (PEAR::isError($aPointDetails['aExtraTags'])) { // possible timeout
|
||||
$aPointDetails['aExtraTags'] = array();
|
||||
}
|
||||
|
||||
// Address
|
||||
$aAddressLines = false;
|
||||
@@ -180,6 +191,9 @@ if ($bIncludeLinkedPlaces) {
|
||||
$sSQL .= " get_name_by_language(name, $sLanguagePrefArraySQL), ";
|
||||
$sSQL .= ' housenumber';
|
||||
$aLinkedLines = $oDB->getAll($sSQL);
|
||||
if (PEAR::isError($aLinkedLines)) { // possible timeout
|
||||
$aLinkedLines = array();
|
||||
}
|
||||
}
|
||||
|
||||
// All places this is an imediate parent of
|
||||
@@ -211,25 +225,31 @@ if ($bIncludeHierarchy) {
|
||||
$sSQL .= ' localname, ';
|
||||
$sSQL .= ' housenumber';
|
||||
$aHierarchyLines = $oDB->getAll($sSQL);
|
||||
if (PEAR::isError($aHierarchyLines)) { // possible timeout
|
||||
$aHierarchyLines = array();
|
||||
}
|
||||
}
|
||||
|
||||
$aPlaceSearchNameKeywords = false;
|
||||
$aPlaceSearchAddressKeywords = false;
|
||||
if ($bIncludeKeywords) {
|
||||
$sSQL = "SELECT * FROM search_name WHERE place_id = $iPlaceID";
|
||||
$aPlaceSearchName = $oDB->getRow($sSQL);
|
||||
$aPlaceSearchName = $oDB->getRow($sSQL); // can be null
|
||||
if (!$aPlaceSearchName || PEAR::isError($aPlaceSearchName)) { // possible timeout
|
||||
$aPlaceSearchName = array();
|
||||
}
|
||||
|
||||
if (!empty($aPlaceSearchName)) {
|
||||
$sWordIds = substr($aPlaceSearchName['name_vector'], 1, -1);
|
||||
if (!empty($sWordIds)) {
|
||||
$sSQL = 'SELECT * FROM word WHERE word_id in ('.$sWordIds.')';
|
||||
$aPlaceSearchNameKeywords = $oDB->getAll($sSQL);
|
||||
$sSQL = 'SELECT * FROM word WHERE word_id in ('.substr($aPlaceSearchName['name_vector'], 1, -1).')';
|
||||
$aPlaceSearchNameKeywords = $oDB->getAll($sSQL);
|
||||
if (PEAR::isError($aPlaceSearchNameKeywords)) { // possible timeout
|
||||
$aPlaceSearchNameKeywords = array();
|
||||
}
|
||||
|
||||
$sWordIds = substr($aPlaceSearchName['nameaddress_vector'], 1, -1);
|
||||
if (!empty($sWordIds)) {
|
||||
$sSQL = 'SELECT * FROM word WHERE word_id in ('.$sWordIds.')';
|
||||
$aPlaceSearchAddressKeywords = $oDB->getAll($sSQL);
|
||||
$sSQL = 'SELECT * FROM word WHERE word_id in ('.substr($aPlaceSearchName['nameaddress_vector'], 1, -1).')';
|
||||
$aPlaceSearchAddressKeywords = $oDB->getAll($sSQL);
|
||||
if (PEAR::isError($aPlaceSearchAddressKeywords)) { // possible timeout
|
||||
$aPlaceSearchAddressKeywords = array();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,7 +258,7 @@ logEnd($oDB, $hLog, 1);
|
||||
|
||||
if ($sOutputFormat=='html') {
|
||||
$sSQL = "SELECT TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' FROM import_status LIMIT 1";
|
||||
$sDataDate = $oDB->getOne($sSQL);
|
||||
$sDataDate = chksql($oDB->getOne($sSQL));
|
||||
$sTileURL = CONST_Map_Tile_URL;
|
||||
$sTileAttribution = CONST_Map_Tile_Attribution;
|
||||
}
|
||||
|
||||
@@ -10,19 +10,16 @@ $oParams = new Nominatim\ParameterParser();
|
||||
|
||||
$sOutputFormat = $oParams->getSet('format', array('html', 'json'), 'html');
|
||||
$aLangPrefOrder = $oParams->getPreferredLanguages();
|
||||
|
||||
$sLanguagePrefArraySQL = 'ARRAY['.join(',', array_map('getDBQuoted', $aLangPrefOrder)).']';
|
||||
|
||||
$sPlaceId = $oParams->getString('place_id');
|
||||
$sOsmType = $oParams->getSet('osmtype', array('N', 'W', 'R'));
|
||||
$iOsmId = $oParams->getInt('osmid', -1);
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
|
||||
$sLanguagePrefArraySQL = $oDB->getArraySQL($oDB->getDBQuotedList($aLangPrefOrder));
|
||||
$oDB =& getDB();
|
||||
|
||||
if ($sOsmType && $iOsmId > 0) {
|
||||
$sPlaceId = $oDB->getOne("select place_id from placex where osm_type = '".$sOsmType."' and osm_id = ".$iOsmId." order by type = 'postcode' asc");
|
||||
$sPlaceId = chksql($oDB->getOne("select place_id from placex where osm_type = '".$sOsmType."' and osm_id = ".$iOsmId." order by type = 'postcode' asc"));
|
||||
|
||||
// Be nice about our error messages for broken geometry
|
||||
if (!$sPlaceId) {
|
||||
@@ -31,7 +28,7 @@ if ($sOsmType && $iOsmId > 0) {
|
||||
$sSQL .= ' ST_AsText(prevgeometry) as prevgeom, ST_AsText(newgeometry) as newgeom';
|
||||
$sSQL .= " from import_polygon_error where osm_type = '".$sOsmType;
|
||||
$sSQL .= "' and osm_id = ".$iOsmId.' order by updated desc limit 1';
|
||||
$aPointDetails = $oDB->getRow($sSQL);
|
||||
$aPointDetails = chksql($oDB->getRow($sSQL));
|
||||
if ($aPointDetails) {
|
||||
if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches)) {
|
||||
$aPointDetails['error_x'] = $aMatches[1];
|
||||
@@ -48,12 +45,12 @@ if (!$sPlaceId) userError('Please select a place id');
|
||||
$iPlaceID = (int)$sPlaceId;
|
||||
|
||||
if (CONST_Use_US_Tiger_Data) {
|
||||
$iParentPlaceID = $oDB->getOne('select parent_place_id from location_property_tiger where place_id = '.$iPlaceID);
|
||||
$iParentPlaceID = chksql($oDB->getOne('select parent_place_id from location_property_tiger where place_id = '.$iPlaceID));
|
||||
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
||||
}
|
||||
|
||||
if (CONST_Use_Aux_Location_data) {
|
||||
$iParentPlaceID = $oDB->getOne('select parent_place_id from location_property_aux where place_id = '.$iPlaceID);
|
||||
$iParentPlaceID = chksql($oDB->getOne('select parent_place_id from location_property_aux where place_id = '.$iPlaceID));
|
||||
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
||||
}
|
||||
|
||||
@@ -89,7 +86,7 @@ if ($sOutputFormat == 'json') {
|
||||
exit;
|
||||
}
|
||||
|
||||
$aRelatedPlaceIDs = $oDB->getCol("select place_id from placex where linked_place_id = $iPlaceID or place_id = $iPlaceID");
|
||||
$aRelatedPlaceIDs = chksql($oDB->getCol($sSQL = "select place_id from placex where linked_place_id = $iPlaceID or place_id = $iPlaceID"));
|
||||
|
||||
$sSQL = 'select obj.place_id, osm_type, osm_id, class, type, housenumber, admin_level,';
|
||||
$sSQL .= " rank_address, ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') as isarea, st_area(geometry) as area, ";
|
||||
@@ -97,7 +94,7 @@ $sSQL .= " get_name_by_language(name,$sLanguagePrefArraySQL) as localname, lengt
|
||||
$sSQL .= ' from (select placex.place_id, osm_type, osm_id, class, type, housenumber, admin_level, rank_address, rank_search, geometry, name from placex ';
|
||||
$sSQL .= ' where parent_place_id in ('.join(',', $aRelatedPlaceIDs).') and name is not null order by rank_address asc,rank_search asc limit 500) as obj';
|
||||
$sSQL .= ' order by rank_address asc,rank_search asc,localname,class, type,housenumber';
|
||||
$aParentOfLines = $oDB->getAll($sSQL);
|
||||
$aParentOfLines = chksql($oDB->getAll($sSQL));
|
||||
|
||||
if (!empty($aParentOfLines)) {
|
||||
echo '<h2>Parent Of:</h2>';
|
||||
@@ -121,7 +118,7 @@ if (!empty($aParentOfLines)) {
|
||||
echo '<div class="line">';
|
||||
echo '<span class="name">'.(trim($aAddressLine['localname'])?$aAddressLine['localname']:'<span class="noname">No Name</span>').'</span>';
|
||||
echo ' (';
|
||||
echo '<span class="area">'.($aAddressLine['isarea']?'Polygon':'Point').'</span>';
|
||||
echo '<span class="area">'.($aAddressLine['isarea']=='t'?'Polygon':'Point').'</span>';
|
||||
if ($sOSMType) echo ', <span class="osm"><span class="label"></span>'.$sOSMType.' '.osmLink($aAddressLine).'</span>';
|
||||
echo ', <a href="hierarchy.php?place_id='.$aAddressLine['place_id'].'">GOTO</a>';
|
||||
echo ', '.$aAddressLine['area'];
|
||||
|
||||
@@ -15,8 +15,7 @@ set_exception_handler_by_format($sOutputFormat);
|
||||
// Preferred language
|
||||
$aLangPrefOrder = $oParams->getPreferredLanguages();
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB =& getDB();
|
||||
|
||||
$hLog = logStart($oDB, 'place', $_SERVER['QUERY_STRING'], $aLangPrefOrder);
|
||||
|
||||
|
||||
@@ -12,10 +12,9 @@ $iDays = $oParams->getInt('days', false);
|
||||
$bReduced = $oParams->getBool('reduced', false);
|
||||
$sClass = $oParams->getString('class', false);
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB =& getDB();
|
||||
|
||||
$iTotalBroken = (int) $oDB->getOne('select count(*) from import_polygon_error');
|
||||
$iTotalBroken = (int) chksql($oDB->getOne('select count(*) from import_polygon_error'));
|
||||
|
||||
$aPolygons = array();
|
||||
while ($iTotalBroken && empty($aPolygons)) {
|
||||
@@ -37,7 +36,7 @@ while ($iTotalBroken && empty($aPolygons)) {
|
||||
}
|
||||
|
||||
$sSQL .= ' order by updated desc limit 1000';
|
||||
$aPolygons = $oDB->getAll($sSQL);
|
||||
$aPolygons = chksql($oDB->getAll($sSQL));
|
||||
}
|
||||
|
||||
if (CONST_Debug) {
|
||||
|
||||
@@ -16,8 +16,7 @@ set_exception_handler_by_format($sOutputFormat);
|
||||
// Preferred language
|
||||
$aLangPrefOrder = $oParams->getPreferredLanguages();
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB =& getDB();
|
||||
|
||||
$hLog = logStart($oDB, 'reverse', $_SERVER['QUERY_STRING'], $aLangPrefOrder);
|
||||
|
||||
@@ -67,7 +66,7 @@ if (isset($aPlace)) {
|
||||
$aPlace = array();
|
||||
}
|
||||
|
||||
logEnd($oDB, $hLog, count($aPlace) ? 1 : 0);
|
||||
logEnd($oDB, $hLog, count($aPlace));
|
||||
|
||||
if (CONST_Debug) {
|
||||
var_dump($aPlace);
|
||||
@@ -75,16 +74,13 @@ if (CONST_Debug) {
|
||||
}
|
||||
|
||||
if ($sOutputFormat == 'html') {
|
||||
$sDataDate = $oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1");
|
||||
$sDataDate = chksql($oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1"));
|
||||
$sTileURL = CONST_Map_Tile_URL;
|
||||
$sTileAttribution = CONST_Map_Tile_Attribution;
|
||||
} elseif ($sOutputFormat == 'geocodejson') {
|
||||
$sQuery = $fLat.','.$fLon;
|
||||
if (isset($aPlace['place_id'])) {
|
||||
$fDistance = $oDB->getOne(
|
||||
'SELECT ST_Distance(ST_SetSRID(ST_Point(:lon,:lat),4326), centroid) FROM placex where place_id = :placeid',
|
||||
array(':lon' => $fLon, ':lat' => $fLat, ':placeid' => $aPlace['place_id'])
|
||||
);
|
||||
$fDistance = chksql($oDB->getOne('SELECT ST_Distance(ST_SetSRID(ST_Point('.$fLon.','.$fLat.'),4326), centroid) FROM placex where place_id='.$aPlace['place_id']));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@ require_once(CONST_BasePath.'/lib/Geocode.php');
|
||||
require_once(CONST_BasePath.'/lib/output.php');
|
||||
ini_set('memory_limit', '200M');
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB->connect();
|
||||
$oDB =& getDB();
|
||||
$oParams = new Nominatim\ParameterParser();
|
||||
|
||||
$oGeocode = new Nominatim\Geocode($oDB);
|
||||
@@ -66,7 +65,7 @@ $hLog = logStart($oDB, 'search', $oGeocode->getQueryString(), $aLangPrefOrder);
|
||||
$aSearchResults = $oGeocode->lookup();
|
||||
|
||||
if ($sOutputFormat=='html') {
|
||||
$sDataDate = $oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1");
|
||||
$sDataDate = chksql($oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1"));
|
||||
}
|
||||
logEnd($oDB, $hLog, count($aSearchResults));
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ require_once(CONST_BasePath.'/lib/Status.php');
|
||||
$oParams = new Nominatim\ParameterParser();
|
||||
$sOutputFormat = $oParams->getSet('format', array('text', 'json'), 'text');
|
||||
|
||||
$oDB = new Nominatim\DB();
|
||||
$oDB = DB::connect(CONST_Database_DSN, false);
|
||||
$oStatus = new Nominatim\Status($oDB);
|
||||
|
||||
|
||||
if ($sOutputFormat == 'json') {
|
||||
header('content-type: application/json; charset=UTF-8');
|
||||
@@ -15,7 +17,6 @@ if ($sOutputFormat == 'json') {
|
||||
|
||||
|
||||
try {
|
||||
$oStatus = new Nominatim\Status($oDB);
|
||||
$oStatus->status();
|
||||
} catch (Exception $oErr) {
|
||||
if ($sOutputFormat == 'json') {
|
||||
|
||||
Reference in New Issue
Block a user