X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/4a321487f3d44241242a1729ab4d137df1f57bfb..75f951d254127d8857b6ad95cac241917f88e542:/lib/db.php diff --git a/lib/db.php b/lib/db.php index 145c57d0..cac6f2cd 100644 --- a/lib/db.php +++ b/lib/db.php @@ -1,38 +1,176 @@ 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 getPostgresVersion(&$oDB) -{ - $sVersionString = $oDB->getOne('select version()'); - preg_match('#PostgreSQL ([0-9]+)[.]([0-9]+)[^0-9]#', $sVersionString, $aMatches); - return (float) ($aMatches[1].'.'.$aMatches[2]); -} + 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 getPostgisVersion(&$oDB) -{ - $sVersionString = $oDB->getOne('select postgis_full_version()'); - preg_match('#POSTGIS="([0-9]+)[.]([0-9]+)[.]([0-9]+)( r([0-9]+))?"#', $sVersionString, $aMatches); - return (float) ($aMatches[1].'.'.$aMatches[2]); + // 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) + { + $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; + } }