X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/d3604b8594ce1c2ec01bac675fc35b49ab8fc7df..f5718ed909f1ff93d238f2c3fac2429a420efbfa:/lib/DB.php diff --git a/lib/DB.php b/lib/DB.php index 17dfe67d..6307d6ca 100644 --- a/lib/DB.php +++ b/lib/DB.php @@ -74,12 +74,7 @@ class DB public function getRow($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); - } + $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage); $row = $stmt->fetch(); } catch (\PDOException $e) { throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL); @@ -98,12 +93,7 @@ class DB public function getOne($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); - } + $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage); $row = $stmt->fetch(\PDO::FETCH_NUM); if ($row === false) return false; } catch (\PDOException $e) { @@ -123,12 +113,7 @@ class DB public function getAll($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); - } + $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage); $rows = $stmt->fetchAll(); } catch (\PDOException $e) { throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL); @@ -148,13 +133,9 @@ class DB { $aVals = array(); try { - if (isset($aInputVars)) { - $stmt = $this->connection->prepare($sSQL); - $stmt->execute($aInputVars); - } else { - $stmt = $this->connection->query($sSQL); - } - while ($val = $stmt->fetchColumn(0)) { // returns first column or false + $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage); + + while (($val = $stmt->fetchColumn(0)) !== false) { // returns first column or false $aVals[] = $val; } } catch (\PDOException $e) { @@ -174,12 +155,8 @@ class DB public function getAssoc($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); - } + $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage); + $aList = array(); while ($aRow = $stmt->fetch(\PDO::FETCH_NUM)) { $aList[$aRow[0]] = $aRow[1]; @@ -190,6 +167,27 @@ class DB 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' @@ -242,6 +240,76 @@ class DB return ($this->getOne($sSQL, array(':tablename' => $sTableName)) == 1); } + /** + * Check if an index exists in the database. Optional filtered by tablename + * + * @param string $sTableName + * + * @return boolean + */ + public function indexExists($sIndexName, $sTableName = null) + { + return in_array($sIndexName, $this->getListOfIndices($sTableName)); + } + + /** + * Returns a list of index names in the database, optional filtered by tablename + * + * @param string $sTableName + * + * @return array + */ + public function getListOfIndices($sTableName = null) + { + // table_name | index_name | column_name + // -----------------------+---------------------------------+-------------- + // country_name | idx_country_name_country_code | country_code + // country_osm_grid | idx_country_osm_grid_geometry | geometry + // import_polygon_delete | idx_import_polygon_delete_osmid | osm_id + // import_polygon_delete | idx_import_polygon_delete_osmid | osm_type + // import_polygon_error | idx_import_polygon_error_osmid | osm_id + // import_polygon_error | idx_import_polygon_error_osmid | osm_type + $sSql = <<< END +SELECT + t.relname as table_name, + i.relname as index_name, + a.attname as column_name +FROM + pg_class t, + pg_class i, + pg_index ix, + pg_attribute a +WHERE + t.oid = ix.indrelid + and i.oid = ix.indexrelid + and a.attrelid = t.oid + and a.attnum = ANY(ix.indkey) + and t.relkind = 'r' + and i.relname NOT LIKE 'pg_%' + FILTERS + ORDER BY + t.relname, + i.relname, + a.attname +END; + + $aRows = null; + if ($sTableName) { + $sSql = str_replace('FILTERS', 'and t.relname = :tablename', $sSql); + $aRows = $this->getAll($sSql, array(':tablename' => $sTableName)); + } else { + $sSql = str_replace('FILTERS', '', $sSql); + $aRows = $this->getAll($sSql); + } + + $aIndexNames = array_unique(array_map(function ($aRow) { + return $aRow['index_name']; + }, $aRows)); + sort($aIndexNames); + + return $aIndexNames; + } + /** * Since the DSN includes the database name, checks if the connection works. * @@ -286,7 +354,7 @@ class DB { // https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php $aInfo = array(); - if (preg_match('/^pgsql:(.+)/', $sDSN, $aMatches)) { + if (preg_match('/^pgsql:(.+)$/', $sDSN, $aMatches)) { foreach (explode(';', $aMatches[1]) as $sKeyVal) { list($sKey, $sVal) = explode('=', $sKeyVal, 2); if ($sKey == 'host') $sKey = 'hostspec';