replace database abstraction DB with PDO

This commit is contained in:
marc tobias
2019-02-24 16:14:36 +01:00
parent b20a534e0c
commit d4b633bfc5
42 changed files with 499 additions and 255 deletions

View File

@@ -5,10 +5,12 @@ namespace Nominatim;
class DatabaseError extends \Exception
{
public function __construct($message, $code = 500, Exception $previous = null, $oSql)
public function __construct($message, $code = 500, Exception $previous = null, $oPDOErr, $sSql = null)
{
parent::__construct($message, $code, $previous);
$this->oSql = $oSql;
// https://secure.php.net/manual/en/class.pdoexception.php
$this->oPDOErr = $oPDOErr;
$this->sSql = $sSql;
}
public function __toString()
@@ -18,15 +20,15 @@ class DatabaseError extends \Exception
public function getSqlError()
{
return $this->oSql->getMessage();
return $this->oPDOErr->getMessage();
}
public function getSqlDebugDump()
{
if (CONST_Debug) {
return var_export($this->oSql, true);
return var_export($this->oPDOErr, true);
} else {
return $this->oSql->getUserInfo();
return $this->sSql;
}
}
}

View File

@@ -527,8 +527,8 @@ class Geocode
$sNormQuery = $this->normTerm($this->sQuery);
Debug::printVar('Normalized query', $sNormQuery);
$sLanguagePrefArraySQL = getArraySQL(
array_map('getDBQuoted', $this->aLangPrefOrder)
$sLanguagePrefArraySQL = $this->oDB->getArraySQL(
$this->oDB->getDBQuotedList($this->aLangPrefOrder)
);
$sQuery = $this->sQuery;
@@ -629,7 +629,7 @@ class Geocode
$aPhrases = array();
foreach ($aInPhrases as $iPhrase => $sPhrase) {
$sPhrase = chksql(
$this->oDB->getOne('SELECT make_standard_name('.getDBQuoted($sPhrase).')'),
$this->oDB->getOne('SELECT make_standard_name('.$this->oDB->getDBQuoted($sPhrase).')'),
'Cannot normalize query string (is it a UTF-8 string?)'
);
if (trim($sPhrase)) {
@@ -647,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(',', array_map('getDBQuoted', $aTokens)).')';
$sSQL .= ' WHERE word_token in ('.join(',', $this->oDB->getDBQuotedList($aTokens)).')';
Debug::printSQL($sSQL);

View File

@@ -52,7 +52,7 @@ class PlaceLookup
{
$aLangs = $oParams->getPreferredLanguages();
$this->aLangPrefOrderSql =
'ARRAY['.join(',', array_map('getDBQuoted', $aLangs)).']';
'ARRAY['.join(',', $this->oDB->getDBQuotedList($aLangs)).']';
$this->bExtraTags = $oParams->getBool('extratags', false);
$this->bNameDetails = $oParams->getBool('namedetails', false);
@@ -132,8 +132,9 @@ class PlaceLookup
public function setLanguagePreference($aLangPrefOrder)
{
$this->aLangPrefOrderSql =
'ARRAY['.join(',', array_map('getDBQuoted', $aLangPrefOrder)).']';
$this->aLangPrefOrderSql = $this->oDB->getArraySQL(
$this->oDB->getDBQuotedList($aLangPrefOrder)
);
}
private function addressImportanceSql($sGeometry, $sPlaceId)
@@ -515,7 +516,7 @@ class PlaceLookup
$aPointPolygon = chksql($this->oDB->getRow($sSQL), 'Could not get outline');
if ($aPointPolygon['place_id']) {
if ($aPointPolygon && $aPointPolygon['place_id']) {
if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null) {
$aOutlineResult['lat'] = $aPointPolygon['centrelat'];
$aOutlineResult['lon'] = $aPointPolygon['centrelon'];

View File

@@ -504,8 +504,10 @@ class SearchDescription
Debug::printSQL($sSQL);
$iPlaceId = $oDB->getOne($sSQL);
$aResults = array();
foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
if ($iPlaceId) {
$aResults[$iPlaceId] = new Result($iPlaceId);
}
@@ -577,7 +579,7 @@ 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 .= ' @> '.getArraySQL($this->aAddress).' AND ';
$sSQL .= ' @> '.$oDB->getArraySQL($this->aAddress).' AND ';
} else {
$sSQL .= 'WHERE ';
}
@@ -633,14 +635,14 @@ class SearchDescription
}
if (!empty($this->aName)) {
$aTerms[] = 'name_vector @> '.getArraySQL($this->aName);
$aTerms[] = 'name_vector @> '.$oDB->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[]) @> '.getArraySQL($this->aAddress);
$aTerms[] = 'array_cat(nameaddress_vector,ARRAY[]::integer[]) @> '.$oDB->getArraySQL($this->aAddress);
} else {
$aTerms[] = 'nameaddress_vector @> '.getArraySQL($this->aAddress);
$aTerms[] = 'nameaddress_vector @> '.$oDB->getArraySQL($this->aAddress);
}
}
@@ -695,7 +697,7 @@ class SearchDescription
if (!empty($this->aFullNameAddress)) {
$sExactMatchSQL = ' ( ';
$sExactMatchSQL .= ' SELECT count(*) FROM ( ';
$sExactMatchSQL .= ' SELECT unnest('.getArraySQL($this->aFullNameAddress).')';
$sExactMatchSQL .= ' SELECT unnest('.$oDB->getArraySQL($this->aFullNameAddress).')';
$sExactMatchSQL .= ' INTERSECT ';
$sExactMatchSQL .= ' SELECT unnest(nameaddress_vector)';
$sExactMatchSQL .= ' ) s';

View File

@@ -3,7 +3,6 @@
namespace Nominatim;
use Exception;
use PEAR;
class Status
{
@@ -16,12 +15,18 @@ class Status
public function status()
{
if (!$this->oDB || PEAR::isError($this->oDB)) {
if (!$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 (PEAR::isError($sStandardWord)) {
if ($sStandardWord === false) {
throw new Exception('Module failed', 701);
}
@@ -32,7 +37,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 (PEAR::isError($iWordID)) {
if ($iWordID === false) {
throw new Exception('Query failed', 703);
}
if (!$iWordID) {
@@ -45,7 +50,7 @@ class Status
$sSQL = 'SELECT EXTRACT(EPOCH FROM lastimportdate) FROM import_status LIMIT 1';
$iDataDateEpoch = $this->oDB->getOne($sSQL);
if (PEAR::isError($iDataDateEpoch)) {
if ($iDataDateEpoch === false) {
throw Exception('Data date query failed '.$iDataDateEpoch->getMessage(), 705);
}

View File

@@ -85,7 +85,7 @@ 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(',', array_map('getDBQuoted', $aTokens)).')';
$sSQL .= join(',', $oDB->getDBQuotedList($aTokens)).')';
Debug::printSQL($sSQL);

View File

@@ -122,10 +122,6 @@ function showUsage($aSpec, $bExit = false, $sError = false)
function chksql($oSql, $sMsg = false)
{
if (PEAR::isError($oSql)) {
fail($sMsg || $oSql->getMessage(), $oSql->userinfo);
}
return $oSql;
}
@@ -155,7 +151,7 @@ function repeatWarnings()
function runSQLScript($sScript, $bfatal = true, $bVerbose = false, $bIgnoreErrors = false)
{
// Convert database DSN to psql parameters
$aDSNInfo = DB::parseDSN(CONST_Database_DSN);
$aDSNInfo = \Nominatim\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']) {

View File

@@ -1,43 +1,176 @@
<?php
require_once('DB.php');
namespace Nominatim;
require_once(CONST_BasePath.'/lib/DatabaseError.php');
function &getDB($bNew = false, $bPersistent = false)
class DB
{
// 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;
}
public $connection;
function getDBQuoted($s)
{
return "'".pg_escape_string($s)."'";
}
public function __construct($sDSN = CONST_Database_DSN)
{
$this->sDSN = $sDSN;
}
function getArraySQL($a)
{
return 'ARRAY['.join(',', $a).']';
}
public function connect($bNew = false, $bPersistent = true)
{
$aConnOptions = array(
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_PERSISTENT => $bPersistent
);
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]);
}
// 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());
}
function getPostgisVersion(&$oDB)
{
$sVersionString = $oDB->getOne('select postgis_lib_version()');
preg_match('#^([0-9]+)[.]([0-9]+)[.]#', $sVersionString, $aMatches);
return (float) ($aMatches[1].'.'.$aMatches[2]);
$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)
{
$val = null;
try {
$val = $this->connection->exec($sSQL);
} catch (\PDOException $e) {
throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
}
return $val;
}
public function getRow($sSQL)
{
try {
$stmt = $this->connection->query($sSQL);
$row = $stmt->fetch();
} catch (\PDOException $e) {
throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
}
return $row;
}
public function getOne($sSQL)
{
try {
$stmt = $this->connection->query($sSQL);
$row = $stmt->fetch(\PDO::FETCH_NUM);
if ($row === false) return false;
} catch (\PDOException $e) {
throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
}
return $row[0];
}
public function getAll($sSQL)
{
try {
$stmt = $this->connection->query($sSQL);
$rows = $stmt->fetchAll();
} catch (\PDOException $e) {
throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
}
return $rows;
}
public function getCol($sSQL)
{
$aVals = array();
try {
$stmt = $this->connection->query($sSQL);
while ($val = $stmt->fetchColumn(0)) { // returns first column or false
$aVals[] = $val;
}
} catch (\PDOException $e) {
throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
}
return $aVals;
}
public function getAssoc($sSQL)
{
try {
$stmt = $this->connection->query($sSQL);
$aList = array();
while ($aRow = $stmt->fetch(\PDO::FETCH_NUM)) {
$aList[$aRow[0]] = $aRow[1];
}
} catch (\PDOException $e) {
throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
}
return $aList;
}
// St. John's Way => 'St. John\'s Way'
public function getDBQuoted($sVal)
{
return $this->connection->quote($sVal);
}
public function getDBQuotedList($aVals)
{
return array_map(function ($sVal) {
return $this->getDBQuoted($sVal);
}, $aVals);
}
public function getArraySQL($a)
{
return 'ARRAY['.join(',', $a).']';
}
public function getLastError()
{
// https://secure.php.net/manual/en/pdo.errorinfo.php
return $this->connection->errorInfo();
}
public function tableExists($sTableName)
{
$sSQL = 'SELECT count(*) FROM pg_tables WHERE tablename = '.$this->getDBQuoted($sTableName);
return ($this->getOne($sSQL) == 1);
}
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]);
}
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;
}
}

View File

@@ -2,7 +2,6 @@
require_once('init.php');
require_once('ParameterParser.php');
require_once('DatabaseError.php');
require_once(CONST_Debug ? 'DebugHtml.php' : 'DebugNone.php');
/***************************************************************************
@@ -14,9 +13,7 @@ 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);
return $oSql;
}

View File

@@ -4,7 +4,7 @@ function fail($sError, $sUserError = false)
{
if (!$sUserError) $sUserError = $sError;
error_log('ERROR: '.$sError);
echo $sUserError."\n";
var_dump($sUserError)."\n";
exit(-1);
}

View File

@@ -36,8 +36,18 @@ 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 ('.getDBQuoted($sType).','.getDBQuoted($hLog[0]).','.getDBQuoted($hLog[2]);
$sSQL .= ','.getDBQuoted($hLog[1]).','.getDBQuoted($sUserAgent).','.getDBQuoted(join(',', $aLanguageList)).','.getDBQuoted($sOutputFormat).','.getDBQuoted($hLog[3]).')';
$sSQL .= ' values ('.
$sSQL .= join(',', $oDB->getDBQuotedList(array(
$sType,
$hLog[0],
$hLog[2],
$hLog[1],
$sUserAgent,
join(',', $aLanguageList),
$sOutputFormat,
$hLog[3]
)));
$sSQL .= ')';
$oDB->query($sSQL);
}
@@ -53,10 +63,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 = '.getDBQuoted($sEndTime).', results = '.$iNumResults;
$sSQL .= ' where starttime = '.getDBQuoted($hLog[0]);
$sSQL .= ' and ipaddress = '.getDBQuoted($hLog[1]);
$sSQL .= ' and query = '.getDBQuoted($hLog[2]);
$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]);
$oDB->query($sSQL);
}

View File

@@ -53,21 +53,21 @@ class AddressLevelParser
*/
public function createTable($oDB, $sTable)
{
chksql($oDB->query('DROP TABLE IF EXISTS '.$sTable));
chksql($oDB->exec('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)';
chksql($oDB->query($sSql));
chksql($oDB->exec($sSql));
$sSql = 'CREATE UNIQUE INDEX ON '.$sTable.'(country_code, class, type)';
chksql($oDB->query($sSql));
chksql($oDB->exec($sSql));
$sSql = 'INSERT INTO '.$sTable.' VALUES ';
foreach ($this->aLevels as $aLevel) {
$aCountries = array();
if (isset($aLevel['countries'])) {
foreach ($aLevel['countries'] as $sCountry) {
$aCountries[$sCountry] = getDBQuoted($sCountry);
$aCountries[$sCountry] = $oDB->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(
getDBQuoted($sKey),
$sValue ? getDBQuoted($sValue) : 'NULL'
$oDB->getDBQuoted($sKey),
$sValue ? $oDB->getDBQuoted($sValue) : 'NULL'
);
if (is_array($mRanks)) {
$aFields[] = (string) $mRanks[0];
@@ -93,6 +93,6 @@ class AddressLevelParser
}
}
}
chksql($oDB->query(rtrim($sSql, ',')));
chksql($oDB->exec(rtrim($sSql, ',')));
}
}

View File

@@ -40,7 +40,7 @@ class SetupFunctions
info('module path: ' . $this->sModulePath);
// parse database string
$this->aDSNInfo = array_filter(\DB::parseDSN(CONST_Database_DSN));
$this->aDSNInfo = \Nominatim\DB::parseDSN(CONST_Database_DSN);
if (!isset($this->aDSNInfo['port'])) {
$this->aDSNInfo['port'] = 5432;
}
@@ -74,8 +74,15 @@ class SetupFunctions
public function createDB()
{
info('Create DB');
$sDB = \DB::connect(CONST_Database_DSN, false);
if (!\PEAR::isError($sDB)) {
$bExists = true;
try {
$oDB = new \Nominatim\DB;
$oDB->connect();
} catch (\Nominatim\DatabaseError $e) {
$bExists = false;
}
if ($bExists) {
fail('database already exists ('.CONST_Database_DSN.')');
}
@@ -94,14 +101,15 @@ class SetupFunctions
public function connect()
{
$this->oDB =& getDB();
$this->oDB = new \Nominatim\DB();
$this->oDB->connect();
}
public function setupDB()
{
info('Setup DB');
$fPostgresVersion = getPostgresVersion($this->oDB);
$fPostgresVersion = $this->oDB->getPostgresVersion();
echo 'Postgres version found: '.$fPostgresVersion."\n";
if ($fPostgresVersion < 9.01) {
@@ -122,7 +130,7 @@ class SetupFunctions
}
$fPostgisVersion = getPostgisVersion($this->oDB);
$fPostgisVersion = $this->oDB->getPostgisVersion();
echo 'Postgis version found: '.$fPostgisVersion."\n";
if ($fPostgisVersion < 2.1) {
@@ -379,6 +387,7 @@ class SetupFunctions
$sSQL = 'select distinct partition from country_name';
$aPartitions = chksql($this->oDB->getCol($sSQL));
if (!$this->bNoPartitions) $aPartitions[] = 0;
foreach ($aPartitions as $sPartition) {
$this->pgExec('TRUNCATE location_road_'.$sPartition);
@@ -399,34 +408,48 @@ 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++) {
$aDBInstances[$i] =& getDB(true);
// 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++) {
$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]->connection, $sSQL)) {
fail(pg_last_error($aDBInstances[$i]->connection));
if (!pg_send_query($aDBInstances[$i], $sSQL)) {
fail(pg_last_error($aDBInstances[$i]));
}
}
// last thread for interpolation lines
$aDBInstances[$iLoadThreads] =& getDB(true);
// 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]);
$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]->connection, $sSQL)) {
fail(pg_last_error($aDBInstances[$iLoadThreads]->connection));
if (!pg_send_query($aDBInstances[$iLoadThreads], $sSQL)) {
fail(pg_last_error($aDBInstances[$iLoadThreads]));
}
$bFailed = false;
for ($i = 0; $i <= $iLoadThreads; $i++) {
while (($hPGresult = pg_get_result($aDBInstances[$i]->connection)) !== false) {
while (($hPGresult = pg_get_result($aDBInstances[$i])) !== false) {
$resultStatus = pg_result_status($hPGresult);
// PGSQL_EMPTY_QUERY, PGSQL_COMMAND_OK, PGSQL_TUPLES_OK,
// PGSQL_COPY_OUT, PGSQL_COPY_IN, PGSQL_BAD_RESPONSE,
@@ -442,17 +465,22 @@ 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);
pg_query($this->oDB->connection, 'TRUNCATE import_status');
if ($sDatabaseDate === false) {
$this->oDB->exec('TRUNCATE import_status');
if (!$sDatabaseDate) {
warn('could not determine database date.');
} else {
$sSQL = "INSERT INTO import_status (lastimportdate) VALUES('".$sDatabaseDate."')";
pg_query($this->oDB->connection, $sSQL);
$this->oDB->exec($sSQL);
echo "Latest data imported from $sDatabaseDate.\n";
}
}
@@ -477,7 +505,12 @@ class SetupFunctions
$aDBInstances = array();
for ($i = 0; $i < $this->iInstances; $i++) {
$aDBInstances[$i] =& getDB(true);
// 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]);
}
foreach (glob(CONST_Tiger_Data_Path.'/*.sql') as $sFile) {
@@ -487,11 +520,11 @@ class SetupFunctions
$iLines = 0;
while (true) {
for ($i = 0; $i < $this->iInstances; $i++) {
if (!pg_connection_busy($aDBInstances[$i]->connection)) {
while (pg_get_result($aDBInstances[$i]->connection));
if (!pg_connection_busy($aDBInstances[$i])) {
while (pg_get_result($aDBInstances[$i]));
$sSQL = fgets($hFile, 100000);
if (!$sSQL) break 2;
if (!pg_send_query($aDBInstances[$i]->connection, $sSQL)) fail(pg_last_error($this->oDB->connection));
if (!pg_send_query($aDBInstances[$i], $sSQL)) fail(pg_last_error($aDBInstances[$i]));
$iLines++;
if ($iLines == 1000) {
echo '.';
@@ -507,13 +540,17 @@ class SetupFunctions
while ($bAnyBusy) {
$bAnyBusy = false;
for ($i = 0; $i < $this->iInstances; $i++) {
if (pg_connection_busy($aDBInstances[$i]->connection)) $bAnyBusy = true;
if (pg_connection_busy($aDBInstances[$i])) $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);
@@ -711,7 +748,7 @@ class SetupFunctions
}
foreach ($aDropTables as $sDrop) {
if ($this->bVerbose) echo "Dropping table $sDrop\n";
@pg_query($this->oDB->connection, "DROP TABLE $sDrop CASCADE");
$this->oDB->exec("DROP TABLE $sDrop CASCADE");
// ignore warnings/errors as they might be caused by a table having
// been deleted already by CASCADE
}
@@ -776,7 +813,7 @@ class SetupFunctions
private function pgsqlRunPartitionScript($sTemplate)
{
$sSQL = 'select distinct partition from country_name';
$aPartitions = chksql($this->oDB->getCol($sSQL));
$aPartitions = $this->oDB->getCol($sSQL);
if (!$this->bNoPartitions) $aPartitions[] = 0;
preg_match_all('#^-- start(.*?)^-- end#ms', $sTemplate, $aMatches, PREG_SET_ORDER);
@@ -883,9 +920,7 @@ class SetupFunctions
*/
private function pgExec($sSQL)
{
if (!pg_query($this->oDB->connection, $sSQL)) {
fail(pg_last_error($this->oDB->connection));
}
$this->oDB->exec($sSQL);
}
/**
@@ -895,7 +930,6 @@ class SetupFunctions
*/
private function dbReverseOnly()
{
$sSQL = "SELECT count(*) FROM pg_tables WHERE tablename = 'search_name'";
return !(chksql($this->oDB->getOne($sSQL)));
return !($this->oDB->tableExists('search_name'));
}
}

View File

@@ -24,15 +24,17 @@ function checkModulePresence()
$sSQL .= $sModulePath . "/nominatim.so', 'transliteration' LANGUAGE c IMMUTABLE STRICT";
$sSQL .= ';DROP FUNCTION nominatim_test_import_func(text);';
$oDB = &getDB();
$oResult = $oDB->query($sSQL);
$oDB = new \Nominatim\DB();
$oDB->connect();
$bResult = true;
if (PEAR::isError($oResult)) {
try {
$oDB->exec($sSQL);
} catch (\Nominatim\DatabaseError $e) {
echo "\nERROR: Failed to load nominatim module. Reason:\n";
echo $oResult->userinfo . "\n\n";
echo $oDB->getLastError()[2] . "\n\n";
$bResult = false;
}
return $bResult;
}