The code must be built in a separate directory. Create this directory,
then configure and build Nominatim in there:
+
mkdir build
cd build
cmake $USERHOME/Nominatim
If you want to run the test suite, you need to install the following
additional packages:
- sudo apt-get install -y python3-dev python3-pip python3-psycopg2 python3-tidylib phpunit
+ sudo apt-get install -y python3-setuptools python3-dev python3-pip \
+ python3-psycopg2 python3-tidylib phpunit php-cgi
pip3 install --user behave nose # urllib3
sudo pear install PHP_CodeSniffer
The code must be built in a separate directory. Create this directory,
then configure and build Nominatim in there:
+
mkdir build
cd build
cmake $USERHOME/Nominatim
$aViewbox = $oParams->getStringList('viewboxlbrt');
if ($aViewbox) {
if (count($aViewbox) != 4) {
- userError("Bad parmater 'viewbox'. Expected 4 coordinates.");
+ userError("Bad parmater 'viewboxlbrt'. Expected 4 coordinates.");
}
$this->setViewbox($aViewbox);
} else {
$this->aAddressRankList = array();
$this->aStructuredQuery = array();
- $this->sAllowedTypesSQLList = '';
+ $this->sAllowedTypesSQLList = False;
$this->loadStructuredAddressElement($sAmenity, 'amenity', 26, 30, false);
$this->loadStructuredAddressElement($sStreet, 'street', 26, 30, false);
if (sizeof($this->aStructuredQuery) > 0) {
$this->sQuery = join(', ', $this->aStructuredQuery);
if ($this->iMaxAddressRank < 30) {
- $sAllowedTypesSQLList = '(\'place\',\'boundary\')';
+ $this->sAllowedTypesSQLList = '(\'place\',\'boundary\')';
}
}
}
// Any 'special' terms in the search?
$bSpecialTerms = false;
- preg_match_all('/\\[(.*)=(.*)\\]/', $sQuery, $aSpecialTermsRaw, PREG_SET_ORDER);
- $aSpecialTerms = array();
+ preg_match_all('/\\[([\\w_]*)=([\\w_]*)\\]/', $sQuery, $aSpecialTermsRaw, PREG_SET_ORDER);
foreach ($aSpecialTermsRaw as $aSpecialTerm) {
$sQuery = str_replace($aSpecialTerm[0], ' ', $sQuery);
- $aSpecialTerms[strtolower($aSpecialTerm[1])] = $aSpecialTerm[2];
+ if (!$bSpecialTerms) {
+ $aNewSearches = array();
+ foreach ($aSearches as $aSearch) {
+ $aNewSearch = $aSearch;
+ $aNewSearch['sClass'] = $aSpecialTerm[1];
+ $aNewSearch['sType'] = $aSpecialTerm[2];
+ $aNewSearches[] = $aNewSearch;
+ }
+
+ $aSearches = $aNewSearches;
+ $bSpecialTerms = true;
+ }
}
preg_match_all('/\\[([\\w ]*)\\]/u', $sQuery, $aSpecialTermsRaw, PREG_SET_ORDER);
- $aSpecialTerms = array();
if (isset($this->aStructuredQuery['amenity']) && $this->aStructuredQuery['amenity']) {
$aSpecialTermsRaw[] = array('['.$this->aStructuredQuery['amenity'].']', $this->aStructuredQuery['amenity']);
unset($this->aStructuredQuery['amenity']);
foreach ($aSpecialTermsRaw as $aSpecialTerm) {
$sQuery = str_replace($aSpecialTerm[0], ' ', $sQuery);
+ if ($bSpecialTerms) {
+ continue;
+ }
+
$sToken = chksql($this->oDB->getOne("SELECT make_standard_name('".$aSpecialTerm[1]."') AS string"));
$sSQL = 'SELECT * ';
$sSQL .= 'FROM ( ';
$sSQL .= ' FROM word ';
$sSQL .= ' WHERE word_token in (\' '.$sToken.'\')';
$sSQL .= ') AS x ';
- $sSQL .= ' WHERE (class is not null AND class not in (\'place\')) ';
- $sSQL .= ' OR country_code is not null';
+ $sSQL .= ' WHERE (class is not null AND class not in (\'place\'))';
if (CONST_Debug) var_Dump($sSQL);
$aSearchWords = chksql($this->oDB->getAll($sSQL));
$aNewSearches = array();
foreach ($aSearches as $aSearch) {
foreach ($aSearchWords as $aSearchTerm) {
$aNewSearch = $aSearch;
- if ($aSearchTerm['country_code']) {
- $aNewSearch['sCountryCode'] = strtolower($aSearchTerm['country_code']);
- $aNewSearches[] = $aNewSearch;
- $bSpecialTerms = true;
- }
- if ($aSearchTerm['class']) {
- $aNewSearch['sClass'] = $aSearchTerm['class'];
- $aNewSearch['sType'] = $aSearchTerm['type'];
- $aNewSearches[] = $aNewSearch;
- $bSpecialTerms = true;
- }
+ $aNewSearch['sClass'] = $aSearchTerm['class'];
+ $aNewSearch['sType'] = $aSearchTerm['type'];
+ $aNewSearches[] = $aNewSearch;
+ $bSpecialTerms = true;
}
}
$aSearches = $aNewSearches;
}
// No location term?
- if (!sizeof($aSearch['aName']) && !sizeof($aSearch['aAddress']) && !$aSearch['oNear']) {
- if ($aSearch['sCountryCode'] && !$aSearch['sClass'] && !$aSearch['sHouseNumber']) {
+ if (!sizeof($aSearch['aName']) && !sizeof($aSearch['aAddress'])) {
+ if ($aSearch['sCountryCode'] && !$aSearch['sClass'] && !$aSearch['sHouseNumber'] && !$aSearch['oNear']) {
// Just looking for a country by code - look it up
if (4 >= $this->iMinAddressRank && 4 <= $this->iMaxAddressRank) {
$sSQL = "SELECT place_id FROM placex WHERE country_code='".$aSearch['sCountryCode']."' AND rank_search = 4";
if (chksql($this->oDB->getOne($sSQL))) {
$sSQL = "SELECT place_id FROM place_classtype_".$aSearch['sClass']."_".$aSearch['sType']." ct";
if ($sCountryCodesSQL) $sSQL .= " JOIN placex USING (place_id)";
- $sSQL .= " WHERE st_contains($this->sViewboxSmallSQL, ct.centroid)";
+ if ($aSearch['oNear']) {
+ $sSQL .= " WHERE ".$aSearch['oNear']->withinSQL('ct.centroid');
+ } else {
+ $sSQL .= " WHERE st_contains($this->sViewboxSmallSQL, ct.centroid)";
+ }
if ($sCountryCodesSQL) $sSQL .= " AND country_code in ($sCountryCodesSQL)";
if (sizeof($this->aExcludePlaceIDs)) {
$sSQL .= " AND place_id not in (".join(',', $this->aExcludePlaceIDs).")";
}
- if ($this->sViewboxCentreSQL) $sSQL .= " ORDER BY ST_Distance($this->sViewboxCentreSQL, ct.centroid) ASC";
+ if ($this->sViewboxCentreSQL) {
+ $sSQL .= " ORDER BY ST_Distance($this->sViewboxCentreSQL, ct.centroid) ASC";
+ } elseif ($aSearch['oNear']) {
+ $sSQL .= " ORDER BY ".$aSearch['oNear']->distanceSQL('ct.centroid').' ASC';
+ }
$sSQL .= " limit $this->iLimit";
if (CONST_Debug) var_dump($sSQL);
$aPlaceIDs = chksql($this->oDB->getCol($sSQL));
-
- // If excluded place IDs are given, it is fair to assume that
- // there have been results in the small box, so no further
- // expansion in that case.
- // Also don't expand if bounded results were requested.
- if (!sizeof($aPlaceIDs) && !sizeof($this->aExcludePlaceIDs) && !$this->bBoundedSearch) {
- $sSQL = "SELECT place_id FROM place_classtype_".$aSearch['sClass']."_".$aSearch['sType']." ct";
- if ($sCountryCodesSQL) $sSQL .= " join placex using (place_id)";
- $sSQL .= " WHERE ST_Contains($this->sViewboxLargeSQL, ct.centroid)";
- if ($sCountryCodesSQL) $sSQL .= " AND country_code in ($sCountryCodesSQL)";
- if ($this->sViewboxCentreSQL) $sSQL .= " ORDER BY ST_Distance($this->sViewboxCentreSQL, ct.centroid) ASC";
- $sSQL .= " LIMIT $this->iLimit";
- if (CONST_Debug) var_dump($sSQL);
- $aPlaceIDs = chksql($this->oDB->getCol($sSQL));
- }
- } else {
+ } else if ($aSearch['oNear']) {
$sSQL = "SELECT place_id ";
$sSQL .= "FROM placex ";
$sSQL .= "WHERE class='".$aSearch['sClass']."' ";
$sSQL .= " AND type='".$aSearch['sType']."'";
- $sSQL .= " AND ST_Contains($this->sViewboxSmallSQL, geometry) ";
+ $sSQL .= " AND ".$aSearch['oNear']->withinSQL('geometry');
$sSQL .= " AND linked_place_id is null";
if ($sCountryCodesSQL) $sSQL .= " AND country_code in ($sCountryCodesSQL)";
- if ($this->sViewboxCentreSQL) $sSQL .= " ORDER BY ST_Distance($this->sViewboxCentreSQL, centroid) ASC";
+ $sSQL .= " ORDER BY ".$aSearch['oNear']->distanceSQL('centroid')." ASC";
$sSQL .= " LIMIT $this->iLimit";
if (CONST_Debug) var_dump($sSQL);
$aPlaceIDs = chksql($this->oDB->getCol($sSQL));
if ($aSearch['sCountryCode']) $aTerms[] = "country_code = '".pg_escape_string($aSearch['sCountryCode'])."'";
if ($aSearch['sHouseNumber']) {
$aTerms[] = "address_rank between 16 and 27";
- } else {
+ } elseif (!$aSearch['sClass'] || $aSearch['sOperator'] == 'name') {
if ($this->iMinAddressRank > 0) {
$aTerms[] = "address_rank >= ".$this->iMinAddressRank;
}
} elseif ($sPlaceIDs) {
$sOrderBySQL = "ST_Distance(l.centroid, f.geometry)";
} elseif ($sPlaceGeom) {
- $sOrderBysSQL = "ST_Distance(st_centroid('".$sPlaceGeom."'), l.centroid)";
+ $sOrderBySQL = "ST_Distance(st_centroid('".$sPlaceGeom."'), l.centroid)";
}
$sSQL = "select distinct i.place_id".($sOrderBySQL?', i.order_term':'')." from (";
$sOrderBySQL = "ST_Distance(l.geometry, f.geometry)";
}
- $sSQL = "SELECT distinct l.place_id".($sOrderBysSQL?','.$sOrderBysSQL:'');
+ $sSQL = "SELECT distinct l.place_id".($sOrderBySQL?','.$sOrderBySQL:'');
$sSQL .= " FROM placex as l, placex as f ";
$sSQL .= " WHERE f.place_id in ($sPlaceIDs) ";
$sSQL .= " AND ST_DWithin(l.geometry, f.centroid, $fRange) ";
$sSQL .= " AND l.place_id not in (".join(',', $this->aExcludePlaceIDs).")";
}
if ($sCountryCodesSQL) $sSQL .= " AND l.country_code in ($sCountryCodesSQL)";
- if ($sOrderBy) $sSQL .= "ORDER BY ".$OrderBysSQL." ASC";
+ if ($sOrderBySQL) $sSQL .= "ORDER BY ".$sOrderBySQL." ASC";
if ($this->iOffset) $sSQL .= " OFFSET $this->iOffset";
$sSQL .= " limit $this->iLimit";
if (CONST_Debug) var_dump($sSQL);
$sFound = $aData[0];
$fQueryLat = ($aData[2]=='N'?1:-1) * ($aData[1]);
$fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[3]);
- } elseif (preg_match('/(\\[|^|\\b)(-?[0-9]+[0-9]*\\.[0-9]+)[, ]+(-?[0-9]+[0-9]*\\.[0-9]+)(\\]|$|\\b)/', $sQuery, $aData)) {
- /* 1 2 3 4
+ } elseif (preg_match('/(\\[|^|\\b)?(-?[0-9]+[0-9]*\\.[0-9]+)[, ]+(-?[0-9]+[0-9]*\\.[0-9]+)(\\]|$|\\b)/', $sQuery, $aData)) {
+ /* 1 2 3 4
* degrees decimal
* 12.34, 56.78
* [12.456,-78.90]
return $oSql;
}
+
+function info($sMsg)
+{
+ echo date('Y-m-d H:i:s == ').$sMsg."\n";
+}
+
+$aWarnings = [];
+
+function warn($sMsg)
+{
+ $GLOBALS['aWarnings'][] = $sMsg;
+ echo date('Y-m-d H:i:s == ').'WARNING: '.$sMsg."\n";
+}
+
+function repeatWarnings()
+{
+ foreach ($GLOBALS['aWarnings'] as $sMsg) {
+ echo ' * ',$sMsg."\n";
+ }
+}
echo "<td>".$aRow['sPostcode']."</td>";
echo "<td>".$aRow['sHouseNumber']."</td>";
- echo "<td>".$aRow['fLat']."</td>";
- echo "<td>".$aRow['fLon']."</td>";
+ echo "<td>".$aRow['oNear']->lat()."</td>";
+ echo "<td>".$aRow['oNear']->lon()."</td>";
echo "<td>".$aRow['fRadius']."</td>";
echo "</tr>";
usleep(1000);
// Aim for one update per second
- if (sleepcount++ > 500)
+ if (sleepcount++ > 1000)
{
rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1);
if(interpolation)
#### Code Coverage
The API tests also support code coverage tests. You need to install
-PHP_CodeCoverage. On Debian/Ubuntu run:
+[PHP_CodeCoverage](https://github.com/sebastianbergmann/php-code-coverage).
+On Debian/Ubuntu run:
- apt-get install php-codecoverage
+ apt-get install php-codecoverage php-xdebug
The run the API tests as follows:
behave api -DPHPCOV=<coverage output dir>
-To generate reports, you can use the phpcov tool:
+The output directory must be an absolute path. To generate reports, you can use
+the [phpcov](https://github.com/sebastianbergmann/phpcov) tool:
phpcov merge --html=<report output dir> <coverage output dir>
| jsonv2 |
| xml |
+ Scenario Outline: Coordinates must be floating-point numbers
+ When sending reverse coordinates <coords>
+ Then a HTTP 400 is returned
+
+ Examples:
+ | coords |
+ | -45.3,; |
+ | gkjd,50 |
+
Scenario Outline: Reverse Geocoding with extratags
When sending <format> reverse coordinates 10.776234290950017,106.70425325632095
| extratags |
And result 0 has not attributes address
And result 0 has bounding box in 46.5,47.5,9,10
+ Scenario: Unknown formats returns a user error
+ When sending search query "Vaduz"
+ | format |
+ | x45 |
+ Then a HTTP 400 is returned
+
Scenario: JSON search with addressdetails
When sending json search query "Montevideo" with address
Then address of result 0 is
| city |
| Montevideo |
+ Scenario: Country search with bounded viewbox remain in the area
+ When sending json search query "" with address
+ | bounded | viewbox | country |
+ | 1 | -56.16786,-34.84061,-56.12525,-34.86526 | de |
+ Then less than 1 result is returned
+
Scenario: Search with bounded viewboxlbrt in right area
When sending json search query "bar" with address
| bounded | viewboxlbrt |
| ^[^,]*[Rr]estaurant.* |
Scenario: bounded search remains within viewbox, even with no results
- When sending json search query "restaurant"
+ When sending json search query "[restaurant]"
| bounded | viewbox |
| 1 | 43.5403125,-5.6563282,43.54285,-5.662003 |
Then less than 1 result is returned
| ID | state |
| 0 | Florida |
+ Scenario: viewboxes cannot be points
+ When sending json search query "foo"
+ | viewbox |
+ | 1.01,34.6,1.01,34.6 |
+ Then a HTTP 400 is returned
+
+ Scenario Outline: viewbox must have four coordinate numbers
+ When sending json search query "foo"
+ | viewbox |
+ | <viewbox> |
+ Then a HTTP 400 is returned
+
+ Examples:
+ | viewbox |
+ | 34 |
+ | 0.003,-84.4 |
+ | 5.2,4.5542,12.4 |
+ | 23.1,-6,0.11,44.2,9.1 |
+
+ Scenario Outline: viewboxlbrt must have four coordinate numbers
+ When sending json search query "foo"
+ | viewboxlbrt |
+ | <viewbox> |
+ Then a HTTP 400 is returned
+
+ Examples:
+ | viewbox |
+ | 34 |
+ | 0.003,-84.4 |
+ | 5.2,4.5542,12.4 |
+ | 23.1,-6,0.11,44.2,9.1 |
+
Scenario: Overly large limit number for search results
When sending json search query "restaurant"
| limit |
| 4 |
Then exactly 4 results are returned
+ Scenario: Limit parameter must be a number
+ When sending search query "Blue Laguna"
+ | limit |
+ | ); |
+ Then a HTTP 400 is returned
+
Scenario: Restrict to feature type country
When sending xml search query "Uruguay"
Then results contain
| xml | geojson |
| json | geojson |
| jsonv2 | geojson |
+
+ Scenario: Search along a route
+ When sending json search query "restaurant" with address
+ | bounded | routewidth | route |
+ | 1 | 0.1 | -103.23255,44.08198,-103.22516,44.08079 |
+ Then result addresses contain
+ | city |
+ | Rapid City |
--- /dev/null
+@APIDB
+Feature: Searches with postcodes
+ Various searches involving postcodes
+
+ Scenario: US 5+4 ZIP codes are shortened to 5 ZIP codes if not found
+ When sending json search query "57701 1111, us" with address
+ Then result addresses contain
+ | postcode |
+ | 57701 |
+
+ Scenario: Postcode search with address
+ When sending json search query "9486, mauren"
+ Then at least 1 result is returned
+
+ Scenario: Postcode search with country
+ When sending json search query "9486, li" with address
+ Then result addresses contain
+ | country_code |
+ | li |
+
| place_rank |
| 30 |
+ Scenario: Search with specific amenity
+ When sending json search query "[restaurant] Vaduz" with address
+ Then result addresses contain
+ | country |
+ | Liechtenstein |
+ And results contain
+ | class | type |
+ | amenity | restaurant |
+
+ Scenario: Search with key-value amenity
+ When sending json search query "[shop=hifi] hamburg"
+ Then results contain
+ | class | type |
+ | shop | hifi |
+
+ Scenario: With multiple amenity search only the first is used
+ When sending json search query "[shop=hifi] [church] hamburg"
+ Then results contain
+ | class | type |
+ | shop | hifi |
+
+ Scenario: With multiple amenity search only the first is used
+ When sending json search query "[church] [restaurant] hamburg"
+ Then results contain
+ | class | type |
+ | amenity | place_of_worship |
+
+ Scenario: POI search near given coordinate
+ When sending json search query "restaurant near 47.16712,9.51100"
+ Then results contain
+ | class | type |
+ | amenity | restaurant |
+
+ Scenario: Arbitrary key/value search near given coordinate
+ When sending json search query "[man_made=mast] 47.15739,9.61264"
+ Then results contain
+ | class | type |
+ | man_made | mast |
+
# https://trac.openstreetmap.org/ticket/5094
Scenario: housenumbers are ordered by complete match first
When sending json search query "6395 geminis, montevideo" with address
| attr | value |
| querystring | Old Palace Road, GU2 7UP, United Kingdom |
+ Scenario: Amenity, city
+ When sending json search query "" with address
+ | city | amenity |
+ | Vaduz | church |
+ Then result addresses contain
+ | country |
+ | Liechtenstein |
+ And results contain
+ | class | type |
+ | amenity | place_of_worship |
+
Scenario: gihub #176
When sending json search query "" with address
| city |
<?php
require_once 'SebastianBergmann/CodeCoverage/autoload.php';
+
+function coverage_shutdown($oCoverage)
+{
+ $oCoverage->stop();
+ $writer = new \SebastianBergmann\CodeCoverage\Report\PHP;
+ $writer->process($oCoverage, $_SERVER['PHP_CODE_COVERAGE_FILE']);
+}
+
$covfilter = new SebastianBergmann\CodeCoverage\Filter();
$covfilter->addDirectoryToWhitelist($_SERVER['COV_PHP_DIR']);
$coverage = new SebastianBergmann\CodeCoverage\CodeCoverage(null, $covfilter);
$coverage->start($_SERVER['COV_TEST_NAME']);
+register_shutdown_function('coverage_shutdown', $coverage);
+
include $_SERVER['COV_SCRIPT_FILENAME'];
-$coverage->stop();
-$writer = new \SebastianBergmann\CodeCoverage\Report\PHP;
-$writer->process($coverage, $_SERVER['PHP_CODE_COVERAGE_FILE']);
context.response = SearchResponse(outp, outfmt, status)
-@when(u'sending (?P<fmt>\S+ )?reverse coordinates (?P<lat>[0-9.-]+)?,(?P<lon>[0-9.-]+)?')
+@when(u'sending (?P<fmt>\S+ )?reverse coordinates (?P<lat>.+)?,(?P<lon>.+)?')
def website_reverse_request(context, fmt, lat, lon):
params = {}
if lat is not None:
$this->assertEquals($aRes['pt']->radius(), 0.1);
$this->assertEquals($aRes['query'], '');
+ $aRes = NearPoint::extractFromQuery(' -12.456,-78.90 ');
+ $this->assertEquals($aRes['pt']->lat(), -12.456);
+ $this->assertEquals($aRes['pt']->lon(), -78.90);
+
// http://en.wikipedia.org/wiki/Geographic_coordinate_conversion
// these all represent the same location
$aQueries = array(
$iInstances = isset($aCMDResult['threads'])?$aCMDResult['threads']:(getProcessorCount()-1);
if ($iInstances < 1) {
$iInstances = 1;
- echo "WARNING: resetting threads to $iInstances\n";
+ warn("resetting threads to $iInstances");
}
if ($iInstances > getProcessorCount()) {
$iInstances = getProcessorCount();
- echo "WARNING: resetting threads to $iInstances\n";
+ warn("resetting threads to $iInstances");
}
// Assume we can steal all the cache memory in the box (unless told otherwise)
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
if ($aCMDResult['create-db'] || $aCMDResult['all']) {
- echo "Create DB\n";
+ info("Create DB");
$bDidSomething = true;
$oDB = DB::connect(CONST_Database_DSN, false);
if (!PEAR::isError($oDB)) {
}
if ($aCMDResult['setup-db'] || $aCMDResult['all']) {
- echo "Setup DB\n";
+ info("Setup DB");
$bDidSomething = true;
- // TODO: path detection, detection memory, etc.
- //
$oDB =& getDB();
$fPostgresVersion = getPostgresVersion($oDB);
if ($iNumFunc == 0) {
pgsqlRunScript("create function hstore_to_json(dummy hstore) returns text AS 'select null::text' language sql immutable");
- echo "WARNING: Postgresql is too old. extratags and namedetails API not available.";
+ warn('Postgresql is too old. extratags and namedetails API not available.');
}
$fPostgisVersion = getPostgisVersion($oDB);
pgsqlRunScript('ALTER FUNCTION ST_Distance_Spheroid(geometry, geometry, spheroid) RENAME TO ST_DistanceSpheroid');
}
+ $i = chksql($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";
+ exit(1);
+ }
+
+ // Try accessing the C module, so we know early if something is wrong
+ // and can simply error out.
+ $sSQL = "CREATE FUNCTION nominatim_test_import_func(text) RETURNS text AS '";
+ $sSQL .= CONST_InstallPath."/module/nominatim.so', 'transliteration' LANGUAGE c IMMUTABLE STRICT";
+ $sSQL .= ';DROP FUNCTION nominatim_test_import_func(text);';
+ $oResult = $oDB->query($sSQL);
+
+ if (PEAR::isError($oResult)) {
+ echo "\nERROR: Failed to load nominatim module. Reason:\n";
+ echo $oResult->userinfo."\n\n";
+ exit(1);
+ }
+
if (!file_exists(CONST_ExtraDataPath.'/country_osm_grid.sql.gz')) {
echo "Error: you need to download the country_osm_grid first:";
echo "\n wget -O ".CONST_ExtraDataPath."/country_osm_grid.sql.gz http://www.nominatim.org/data/country_grid.sql.gz\n";
if (file_exists(CONST_BasePath.'/data/gb_postcode_data.sql.gz')) {
pgsqlRunScriptFile(CONST_BasePath.'/data/gb_postcode_data.sql.gz');
} else {
- echo "WARNING: external UK postcode table not found.\n";
+ warn('external UK postcode table not found.');
}
if (CONST_Use_Extra_US_Postcodes) {
pgsqlRunScriptFile(CONST_BasePath.'/data/us_postcode.sql');
}
if ($aCMDResult['import-data'] || $aCMDResult['all']) {
- echo "Import\n";
+ info('Import data');
$bDidSomething = true;
$osm2pgsql = CONST_Osm2pgsql_Binary;
}
if ($aCMDResult['create-functions'] || $aCMDResult['all']) {
- echo "Functions\n";
+ info('Create Functions');
$bDidSomething = true;
- if (!file_exists(CONST_InstallPath.'/module/nominatim.so')) fail("nominatim module not built");
+ if (!file_exists(CONST_InstallPath.'/module/nominatim.so')) {
+ fail("nominatim module not built");
+ }
create_sql_functions($aCMDResult);
}
if ($aCMDResult['create-tables'] || $aCMDResult['all']) {
+ info('Create Tables');
$bDidSomething = true;
- echo "Tables\n";
$sTemplate = file_get_contents(CONST_BasePath.'/sql/tables.sql');
$sTemplate = str_replace('{www-user}', CONST_Database_Web_User, $sTemplate);
$sTemplate = replace_tablespace(
pgsqlRunScript($sTemplate, false);
// re-run the functions
- echo "Functions\n";
+ info('Recreate Functions');
create_sql_functions($aCMDResult);
}
if ($aCMDResult['create-partition-tables'] || $aCMDResult['all']) {
- echo "Partition Tables\n";
+ info('Create Partition Tables');
$bDidSomething = true;
$sTemplate = file_get_contents(CONST_BasePath.'/sql/partition-tables.src.sql');
if ($aCMDResult['create-partition-functions'] || $aCMDResult['all']) {
- echo "Partition Functions\n";
+ info('Create Partition Functions');
$bDidSomething = true;
$sTemplate = file_get_contents(CONST_BasePath.'/sql/partition-functions.src.sql');
$sWikiArticlesFile = CONST_Wikipedia_Data_Path.'/wikipedia_article.sql.bin';
$sWikiRedirectsFile = CONST_Wikipedia_Data_Path.'/wikipedia_redirect.sql.bin';
if (file_exists($sWikiArticlesFile)) {
- echo "Importing wikipedia articles...";
+ info('Importing wikipedia articles');
pgsqlRunDropAndRestore($sWikiArticlesFile);
- echo "...done\n";
} else {
- echo "WARNING: wikipedia article dump file not found - places will have default importance\n";
+ warn('wikipedia article dump file not found - places will have default importance');
}
if (file_exists($sWikiRedirectsFile)) {
- echo "Importing wikipedia redirects...";
+ info('Importing wikipedia redirects');
pgsqlRunDropAndRestore($sWikiRedirectsFile);
- echo "...done\n";
} else {
- echo "WARNING: wikipedia redirect dump file not found - some place importance values may be missing\n";
+ warn('wikipedia redirect dump file not found - some place importance values may be missing');
}
}
if ($aCMDResult['load-data'] || $aCMDResult['all']) {
- echo "Drop old Data\n";
+ info('Drop old Data');
$bDidSomething = true;
$oDB =& getDB();
// pre-create the word list
if (!$aCMDResult['disable-token-precalc']) {
- echo "Loading word list\n";
+ info('Loading word list');
pgsqlRunScriptFile(CONST_BasePath.'/data/words.sql');
}
- echo "Load Data\n";
+ info('Load Data');
$sColumns = 'osm_type, osm_id, class, type, name, admin_level, address, extratags, geometry';
$aDBInstances = array();
echo '.';
}
echo "\n";
- echo "Reanalysing database...\n";
+ info('Reanalysing database');
pgsqlRunScript('ANALYSE');
$sDatabaseDate = getDatabaseDate($oDB);
pg_query($oDB->connection, 'TRUNCATE import_status');
if ($sDatabaseDate === false) {
- echo "WARNING: could not determine database date.\n";
+ warn('could not determine database date.');
} else {
$sSQL = "INSERT INTO import_status (lastimportdate) VALUES('".$sDatabaseDate."')";
pg_query($oDB->connection, $sSQL);
}
if ($aCMDResult['import-tiger-data']) {
+ info('Import Tiger data');
$bDidSomething = true;
$sTemplate = file_get_contents(CONST_BasePath.'/sql/tiger_import_start.sql');
echo "\n";
}
- echo "Creating indexes\n";
+ 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);
$sTemplate = replace_tablespace(
}
if ($aCMDResult['calculate-postcodes'] || $aCMDResult['all']) {
+ info('Calculate Postcodes');
$bDidSomething = true;
$oDB =& getDB();
if (!pg_query($oDB->connection, 'TRUNCATE location_postcode')) {
$bDidSomething = true;
$sOutputFile = '';
$sBaseCmd = CONST_InstallPath.'/nominatim/nominatim -i -d '.$aDSNInfo['database'].' -P '.$aDSNInfo['port'].' -t '.$iInstances.$sOutputFile;
+ info('Index ranks 0 - 4');
passthruCheckReturn($sBaseCmd.' -R 4');
if (!$aCMDResult['index-noanalyse']) pgsqlRunScript('ANALYSE');
+ info('Index ranks 5 - 25');
passthruCheckReturn($sBaseCmd.' -r 5 -R 25');
if (!$aCMDResult['index-noanalyse']) pgsqlRunScript('ANALYSE');
+ info('Index ranks 26 - 30');
passthruCheckReturn($sBaseCmd.' -r 26');
- echo "Indexing postcodes....\n";
+ info('Index postcodes');
$oDB =& getDB();
$sSQL = 'UPDATE location_postcode SET indexed_status = 0';
if (!pg_query($oDB->connection, $sSQL)) fail(pg_last_error($oDB->connection));
}
if ($aCMDResult['create-search-indices'] || $aCMDResult['all']) {
- echo "Search indices\n";
+ info('Create Search indices');
$bDidSomething = true;
$sTemplate = file_get_contents(CONST_BasePath.'/sql/indices.src.sql');
}
if ($aCMDResult['create-country-names'] || $aCMDResult['all']) {
- echo 'Creating search index for default country names';
+ info('Create search index for default country names');
$bDidSomething = true;
pgsqlRunScript("select getorcreate_country(make_standard_name('uk'), 'gb')");
}
if ($aCMDResult['drop']) {
+ info('Drop tables only required for updates');
// The implementation is potentially a bit dangerous because it uses
// a positive selection of tables to keep, and deletes everything else.
// Including any tables that the unsuspecting user might have manually
if (!$bDidSomething) {
showUsage($aCMDOptions, true);
} else {
- echo "Setup finished.\n";
+ echo "Summary of warnings:\n\n";
+ repeatWarnings();
+ echo "\n";
+ info('Setup finished.');
}
function pgsqlRunScriptFile($sFilename)
{
+ global $aCMDResult;
if (!file_exists($sFilename)) fail('unable to find '.$sFilename);
// Convert database DSN to psql parameters
$aDSNInfo = DB::parseDSN(CONST_Database_DSN);
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
$sCMD = 'psql -p '.$aDSNInfo['port'].' -d '.$aDSNInfo['database'];
+ if (!$aCMDResult['verbose']) {
+ $sCMD .= ' -q';
+ }
$ahGzipPipes = null;
if (preg_match('/\\.gz$/', $sFilename)) {
$aDSNInfo = DB::parseDSN(CONST_Database_DSN);
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
$sCMD = 'psql -p '.$aDSNInfo['port'].' -d '.$aDSNInfo['database'];
+ if (!$aCMDResult['verbose']) {
+ $sCMD .= ' -q';
+ }
if ($bfatal && !$aCMDResult['ignore-errors'])
$sCMD .= ' -v ON_ERROR_STOP=1';
$aDescriptors = array(
# If you want to run the test suite, you need to install the following
# additional packages:
- sudo apt-get install -y python3-dev python3-pip python3-psycopg2 python3-tidylib phpunit
+ sudo apt-get install -y python3-setuptools python3-dev python3-pip \
+ python3-psycopg2 python3-tidylib phpunit php-cgi
pip3 install --user behave nose # urllib3
sudo pear install PHP_CodeSniffer