]> git.openstreetmap.org Git - nominatim.git/commitdiff
Merge remote-tracking branch 'upstream/master'
authorSarah Hoffmann <lonvia@denofr.de>
Sun, 14 Apr 2019 10:07:06 +0000 (12:07 +0200)
committerSarah Hoffmann <lonvia@denofr.de>
Sun, 14 Apr 2019 10:07:06 +0000 (12:07 +0200)
33 files changed:
README.md
docs/admin/Faq.md
lib/AddressDetails.php
lib/DB.php [new file with mode: 0644]
lib/Geocode.php
lib/PlaceLookup.php
lib/ReverseGeocode.php
lib/SearchContext.php
lib/SearchDescription.php
lib/TokenList.php
lib/cmd.php
lib/db.php [deleted file]
lib/init-website.php
lib/init.php
lib/setup/AddressLevelParser.php
lib/setup/SetupClass.php
lib/setup_functions.php
lib/template/details-html.php
lib/template/details-json.php
sql/functions.sql
test/bdd/api/details/simple.feature
test/bdd/api/search/postcode.feature
test/php/Nominatim/DBTest.php
test/php/Nominatim/StatusTest.php
test/php/Nominatim/TokenListTest.php
utils/setup.php
utils/update.php
website/deletable.php
website/details.php
website/hierarchy.php
website/polygons.php
website/reverse.php
website/search.php

index 7e8c776ef94fb3080b4973e909bd8acaa6a932a1..a9a5a3e24c638dca13661485c836fc2964b86feb 100644 (file)
--- a/README.md
+++ b/README.md
@@ -59,5 +59,5 @@ Both bug reports and pull requests are welcome.
 Mailing list
 ============
 
-For questions you can join the geocoding mailinglist, see
+For questions you can join the geocoding mailing list, see
 https://lists.openstreetmap.org/listinfo/geocoding
index 1e874c789bf5b210985a542080ecd41829590fe0..db5e101c83dbfafc579ad03ea693b029343fdb66 100644 (file)
@@ -81,6 +81,14 @@ 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
@@ -104,11 +112,8 @@ 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
 
-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)
-
-
-
+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.
 
 ### Website reports "DB Error: insufficient permissions"
 
index 618e10c908ad0d962bb2f9c37d3f91920497aee4..2d40c84f4efc35e90421798cc14f35a35bde3f68 100644 (file)
@@ -26,12 +26,12 @@ class AddressDetails
         $sSQL .= ' FROM get_addressdata('.$iPlaceID.','.$sHousenumber.')';
         $sSQL .= ' ORDER BY rank_address DESC, isaddress DESC';
 
-        $this->aAddressLines = chksql($oDB->getAll($sSQL));
+        $this->aAddressLines = $oDB->getAll($sSQL);
     }
 
     private static function isAddress($aLine)
     {
-        return $aLine['isaddress'] == 't' || $aLine['type'] == 'country_code';
+        return $aLine['isaddress'] || $aLine['type'] == 'country_code';
     }
 
     public function getAddressDetails($bAll = false)
@@ -49,7 +49,7 @@ class AddressDetails
         $sPrevResult = '';
 
         foreach ($this->aAddressLines as $aLine) {
-            if ($aLine['isaddress'] == 't' && $sPrevResult != $aLine['localname']) {
+            if ($aLine['isaddress'] && $sPrevResult != $aLine['localname']) {
                 $sPrevResult = $aLine['localname'];
                 $aParts[] = $sPrevResult;
             }
diff --git a/lib/DB.php b/lib/DB.php
new file mode 100644 (file)
index 0000000..17dfe67
--- /dev/null
@@ -0,0 +1,300 @@
+<?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 {
+            if (isset($aInputVars)) {
+                $stmt = $this->connection->prepare($sSQL);
+                $stmt->execute($aInputVars);
+            } else {
+                $stmt = $this->connection->query($sSQL);
+            }
+            $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 {
+            if (isset($aInputVars)) {
+                $stmt = $this->connection->prepare($sSQL);
+                $stmt->execute($aInputVars);
+            } else {
+                $stmt = $this->connection->query($sSQL);
+            }
+            $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 {
+            if (isset($aInputVars)) {
+                $stmt = $this->connection->prepare($sSQL);
+                $stmt->execute($aInputVars);
+            } else {
+                $stmt = $this->connection->query($sSQL);
+            }
+            $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 {
+            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
+                $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 {
+            if (isset($aInputVars)) {
+                $stmt = $this->connection->prepare($sSQL);
+                $stmt->execute($aInputVars);
+            } else {
+                $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($sErrMessage, 500, null, $e, $sSQL);
+        }
+        return $aList;
+    }
+
+
+    /**
+     * 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;
+    }
+}
index 94816283c2f1281241db1b54fc17deda152ad131..e2d676862a5f6a3c74cd002d4818e211c0ee9567 100644 (file)
@@ -581,8 +581,9 @@ class Geocode
 
             if ($sSpecialTerm && !$aSearches[0]->hasOperator()) {
                 $sSpecialTerm = pg_escape_string($sSpecialTerm);
-                $sToken = chksql(
-                    $this->oDB->getOne("SELECT make_standard_name('$sSpecialTerm')"),
+                $sToken = $this->oDB->getOne(
+                    'SELECT make_standard_name(:term)',
+                    array(':term' => $sSpecialTerm),
                     'Cannot decode query. Wrong encoding?'
                 );
                 $sSQL = 'SELECT class, type FROM word ';
@@ -590,7 +591,7 @@ class Geocode
                 $sSQL .= '   AND class is not null AND class not in (\'place\')';
 
                 Debug::printSQL($sSQL);
-                $aSearchWords = chksql($this->oDB->getAll($sSQL));
+                $aSearchWords = $this->oDB->getAll($sSQL);
                 $aNewSearches = array();
                 foreach ($aSearches as $oSearch) {
                     foreach ($aSearchWords as $aSearchTerm) {
@@ -628,8 +629,9 @@ class Geocode
             $aTokens = array();
             $aPhrases = array();
             foreach ($aInPhrases as $iPhrase => $sPhrase) {
-                $sPhrase = chksql(
-                    $this->oDB->getOne('SELECT make_standard_name('.$this->oDB->getDBQuoted($sPhrase).')'),
+                $sPhrase = $this->oDB->getOne(
+                    'SELECT make_standard_name(:phrase)',
+                    array(':phrase' => $sPhrase),
                     'Cannot normalize query string (is it a UTF-8 string?)'
                 );
                 if (trim($sPhrase)) {
@@ -830,7 +832,7 @@ class Geocode
                     if ($aFilterSql) {
                         $sSQL = join(' UNION ', $aFilterSql);
                         Debug::printSQL($sSQL);
-                        $aFilteredIDs = chksql($this->oDB->getCol($sSQL));
+                        $aFilteredIDs = $this->oDB->getCol($sSQL);
                     }
 
                     $tempIDs = array();
index c5aea5887c6cfe59ebcdc1ee27c2e64d0e891e79..cf3e4f7be812ea8579f815219665404c0edaf039 100644 (file)
@@ -163,8 +163,8 @@ class PlaceLookup
 
     public function lookupOSMID($sType, $iID)
     {
-        $sSQL = "select place_id from placex where osm_type = '".$sType."' and osm_id = ".$iID;
-        $iPlaceID = chksql($this->oDB->getOne($sSQL));
+        $sSQL = 'select place_id from placex where osm_type = :type and osm_id = :id';
+        $iPlaceID = $this->oDB->getOne($sSQL, array(':type' => $sType, ':id' => $iID));
 
         if (!$iPlaceID) {
             return null;
@@ -425,7 +425,7 @@ class PlaceLookup
 
         $sSQL = join(' UNION ', $aSubSelects);
         Debug::printSQL($sSQL);
-        $aPlaces = chksql($this->oDB->getAll($sSQL), 'Could not lookup place');
+        $aPlaces = $this->oDB->getAll($sSQL, null, 'Could not lookup place');
 
         foreach ($aPlaces as &$aPlace) {
             if ($this->bAddressDetails) {
@@ -514,7 +514,7 @@ class PlaceLookup
                 $sSQL .= $sFrom;
             }
 
-            $aPointPolygon = chksql($this->oDB->getRow($sSQL), 'Could not get outline');
+            $aPointPolygon = $this->oDB->getRow($sSQL, null, 'Could not get outline');
 
             if ($aPointPolygon && $aPointPolygon['place_id']) {
                 if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null) {
index 9601ecf5bd8319589961574888cfd80844f93b32..ff20691a3912457ed99b3746da3f27e93e6f9cb9 100644 (file)
@@ -63,8 +63,9 @@ class ReverseGeocode
         $sSQL .= ' and indexed_status = 0 and startnumber is not NULL ';
         $sSQL .= ' ORDER BY distance ASC limit 1';
 
-        return chksql(
-            $this->oDB->getRow($sSQL),
+        return $this->oDB->getRow(
+            $sSQL,
+            null,
             'Could not determine closest housenumber on an osm interpolation line.'
         );
     }
@@ -92,8 +93,9 @@ class ReverseGeocode
         $sSQL = 'SELECT country_code FROM country_osm_grid';
         $sSQL .= ' WHERE ST_CONTAINS(geometry, '.$sPointSQL.') LIMIT 1';
 
-        $sCountryCode = chksql(
-            $this->oDB->getOne($sSQL),
+        $sCountryCode = $this->oDB->getOne(
+            $sSQL,
+            null,
             'Could not determine country polygon containing the point.'
         );
         if ($sCountryCode) {
@@ -115,10 +117,7 @@ class ReverseGeocode
                 $sSQL .= ' LIMIT 1';
 
                 if (CONST_Debug) var_dump($sSQL);
-                $aPlace = chksql(
-                    $this->oDB->getRow($sSQL),
-                    'Could not determine place node.'
-                );
+                $aPlace = $this->oDB->getRow($sSQL, null, 'Could not determine place node.');
                 if ($aPlace) {
                     return new Result($aPlace['place_id']);
                 }
@@ -134,10 +133,7 @@ class ReverseGeocode
             $sSQL .= ' ORDER BY distance ASC';
 
             if (CONST_Debug) var_dump($sSQL);
-            $aPlace = chksql(
-                $this->oDB->getRow($sSQL),
-                'Could not determine place node.'
-            );
+            $aPlace = $this->oDB->getRow($sSQL, null, 'Could not determine place node.');
             if ($aPlace) {
                 return new Result($aPlace['place_id']);
             }
@@ -178,10 +174,8 @@ class ReverseGeocode
         $sSQL .= ' WHERE ST_CONTAINS(geometry, '.$sPointSQL.' )';
         $sSQL .= ' ORDER BY rank_address DESC LIMIT 1';
 
-        $aPoly = chksql(
-            $this->oDB->getRow($sSQL),
-            'Could not determine polygon containing the point.'
-        );
+        $aPoly = $this->oDB->getRow($sSQL, null, 'Could not determine polygon containing the point.');
+
         if ($aPoly) {
         // if a polygon is found, search for placenodes begins ...
             $iParentPlaceID = $aPoly['parent_place_id'];
@@ -213,10 +207,7 @@ class ReverseGeocode
                 $sSQL .= ' LIMIT 1';
 
                 if (CONST_Debug) var_dump($sSQL);
-                $aPlacNode = chksql(
-                    $this->oDB->getRow($sSQL),
-                    'Could not determine place node.'
-                );
+                $aPlacNode = $this->oDB->getRow($sSQL, null, 'Could not determine place node.');
                 if ($aPlacNode) {
                     return $aPlacNode;
                 }
@@ -271,10 +262,7 @@ class ReverseGeocode
             $sSQL .= ' OR ST_DWithin('.$sPointSQL.', centroid, '.$fSearchDiam.'))';
             $sSQL .= ' ORDER BY distance ASC limit 1';
             if (CONST_Debug) var_dump($sSQL);
-            $aPlace = chksql(
-                $this->oDB->getRow($sSQL),
-                'Could not determine closest place.'
-            );
+            $aPlace = $this->oDB->getRow($sSQL, null, 'Could not determine closest place.');
 
             if (CONST_Debug) var_dump($aPlace);
             if ($aPlace) {
@@ -323,10 +311,7 @@ class ReverseGeocode
                     $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 = chksql(
-                        $this->oDB->getRow($sSQL),
-                        'Could not determine closest place.'
-                    );
+                    $aStreet = $this->oDB->getRow($sSQL, null, 'Could not determine closest place.');
                     if ($aStreet) {
                         if (CONST_Debug) var_dump($aStreet);
                         $oResult = new Result($aStreet['place_id']);
@@ -347,10 +332,7 @@ class ReverseGeocode
                     $sSQL .= ' AND ST_DWithin('.$sPointSQL.', linegeo, 0.001)';
                     $sSQL .= ' ORDER BY distance ASC limit 1';
                     if (CONST_Debug) var_dump($sSQL);
-                    $aPlaceTiger = chksql(
-                        $this->oDB->getRow($sSQL),
-                        'Could not determine closest Tiger place.'
-                    );
+                    $aPlaceTiger = $this->oDB->getRow($sSQL, null, '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);
index 84159b83ca21c660112df8d4c8ed27837ff6ce19..3cb11e8271dc55a4ec982664350ae5ca8bd76fe4 100644 (file)
@@ -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          DB connection to use for computing the box.
+     * @param object   $oDB          Nominatim::DB instance 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 = chksql($oDB->getOne('select '.$sSQL), 'Could not get small viewbox');
+        $sGeom = $oDB->getOne('select '.$sSQL, null, 'Could not get small viewbox');
         $this->sqlViewboxSmall = "'".$sGeom."'::geometry";
 
         $sSQL = 'ST_BUFFER('.$this->sqlViewboxCentre.','.($fRouteWidth/30).')';
-        $sGeom = chksql($oDB->getOne('select '.$sSQL), 'Could not get large viewbox');
+        $sGeom = $oDB->getOne('select '.$sSQL, null, 'Could not get large viewbox');
         $this->sqlViewboxLarge = "'".$sGeom."'::geometry";
     }
 
index fac2197236a203f75f1188dd873e467c37b7cf63..506d4202253f61f909c46f3d1c08275b2c12faa9 100644 (file)
@@ -404,7 +404,7 @@ class SearchDescription
     /**
      * Query database for places that match this search.
      *
-     * @param object  $oDB      Database connection to use.
+     * @param object  $oDB      Nominatim::DB instance 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 = chksql($oDB->getCol($sSQL));
+                $aFilteredPlaceIDs = $oDB->getCol($sSQL);
                 if ($aFilteredPlaceIDs) {
                     foreach ($aFilteredPlaceIDs as $iPlaceId) {
                         $aResults[$iPlaceId]->iResultRank++;
@@ -523,8 +523,7 @@ class SearchDescription
         $aDBResults = array();
         $sPoiTable = $this->poiTable();
 
-        $sSQL = 'SELECT count(*) FROM pg_tables WHERE tablename = \''.$sPoiTable."'";
-        if (chksql($oDB->getOne($sSQL))) {
+        if ($oDB->tableExists($sPoiTable)) {
             $sSQL = 'SELECT place_id FROM '.$sPoiTable.' ct';
             if ($this->oContext->sqlCountryList) {
                 $sSQL .= ' JOIN placex USING (place_id)';
@@ -544,14 +543,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 = chksql($oDB->getCol($sSQL));
+            $aDBResults = $oDB->getCol($sSQL);
         }
 
         if ($this->oContext->hasNearPoint()) {
             $sSQL = 'SELECT place_id FROM placex WHERE ';
-            $sSQL .= 'class=\''.$this->sClass."' and type='".$this->sType."'";
+            $sSQL .= 'class = :class and type = :type';
             $sSQL .= ' AND '.$this->oContext->withinSQL('geometry');
             $sSQL .= ' AND linked_place_id is null';
             if ($this->oContext->sqlCountryList) {
@@ -560,7 +559,10 @@ class SearchDescription
             $sSQL .= ' ORDER BY '.$this->oContext->distanceSQL('centroid').' ASC';
             $sSQL .= " LIMIT $iLimit";
             Debug::printSQL($sSQL);
-            $aDBResults = chksql($oDB->getCol($sSQL));
+            $aDBResults = $oDB->getCol(
+                $sSQL,
+                array(':class' => $this->sClass, ':type' => $this->sType)
+            );
         }
 
         $aResults = array();
@@ -586,13 +588,16 @@ class SearchDescription
 
         $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 (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
+        foreach ($oDB->getCol($sSQL) as $iPlaceId) {
             $aResults[$iPlaceId] = new Result($iPlaceId, Result::TABLE_POSTCODE);
         }
 
@@ -722,10 +727,7 @@ class SearchDescription
 
             Debug::printSQL($sSQL);
 
-            $aDBResults = chksql(
-                $oDB->getAll($sSQL),
-                'Could not get places for search terms.'
-            );
+            $aDBResults = $oDB->getAll($sSQL, null, 'Could not get places for search terms.');
 
             foreach ($aDBResults as $aResult) {
                 $oResult = new Result($aResult['place_id']);
@@ -755,7 +757,7 @@ class SearchDescription
         Debug::printSQL($sSQL);
 
         // XXX should inherit the exactMatches from its parent
-        foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
+        foreach ($oDB->getCol($sSQL) as $iPlaceId) {
             $aResults[$iPlaceId] = new Result($iPlaceId);
         }
 
@@ -781,7 +783,7 @@ class SearchDescription
 
             Debug::printSQL($sSQL);
 
-            foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
+            foreach ($oDB->getCol($sSQL) as $iPlaceId) {
                 $oResult = new Result($iPlaceId, Result::TABLE_OSMLINE);
                 $oResult->iHouseNumber = $iHousenumber;
                 $aResults[$iPlaceId] = $oResult;
@@ -797,7 +799,7 @@ class SearchDescription
 
             Debug::printSQL($sSQL);
 
-            foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
+            foreach ($oDB->getCol($sSQL) as $iPlaceId) {
                 $aResults[$iPlaceId] = new Result($iPlaceId, Result::TABLE_AUX);
             }
         }
@@ -818,7 +820,7 @@ class SearchDescription
 
             Debug::printSQL($sSQL);
 
-            foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
+            foreach ($oDB->getCol($sSQL) as $iPlaceId) {
                 $oResult = new Result($iPlaceId, Result::TABLE_TIGER);
                 $oResult->iHouseNumber = $iHousenumber;
                 $aResults[$iPlaceId] = $oResult;
@@ -852,7 +854,7 @@ class SearchDescription
 
             Debug::printSQL($sSQL);
 
-            foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
+            foreach ($oDB->getCol($sSQL) as $iPlaceId) {
                 $aResults[$iPlaceId] = new Result($iPlaceId);
             }
         }
@@ -860,12 +862,11 @@ class SearchDescription
         // NEAR and IN are handled the same
         if ($this->iOperator == Operator::TYPE || $this->iOperator == Operator::NEAR) {
             $sClassTable = $this->poiTable();
-            $sSQL = "SELECT count(*) FROM pg_tables WHERE tablename = '$sClassTable'";
-            $bCacheTable = (bool) chksql($oDB->getOne($sSQL));
+            $bCacheTable = $oDB->tableExists($sClassTable);
 
             $sSQL = "SELECT min(rank_search) FROM placex WHERE place_id in ($sPlaceIDs)";
             Debug::printSQL($sSQL);
-            $iMaxRank = (int)chksql($oDB->getOne($sSQL));
+            $iMaxRank = (int) $oDB->getOne($sSQL);
 
             // For state / country level searches the normal radius search doesn't work very well
             $sPlaceGeom = false;
@@ -878,7 +879,7 @@ class SearchDescription
                 $sSQL .= ' ORDER BY rank_search ASC ';
                 $sSQL .= ' LIMIT 1';
                 Debug::printSQL($sSQL);
-                $sPlaceGeom = chksql($oDB->getOne($sSQL));
+                $sPlaceGeom = $oDB->getOne($sSQL);
             }
 
             if ($sPlaceGeom) {
@@ -888,7 +889,7 @@ class SearchDescription
                 $sSQL = 'SELECT place_id FROM placex';
                 $sSQL .= " WHERE place_id in ($sPlaceIDs) and rank_search < $iMaxRank";
                 Debug::printSQL($sSQL);
-                $aPlaceIDs = chksql($oDB->getCol($sSQL));
+                $aPlaceIDs = $oDB->getCol($sSQL);
                 $sPlaceIDs = join(',', $aPlaceIDs);
             }
 
@@ -934,7 +935,7 @@ class SearchDescription
 
                     Debug::printSQL($sSQL);
 
-                    foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
+                    foreach ($oDB->getCol($sSQL) as $iPlaceId) {
                         $aResults[$iPlaceId] = new Result($iPlaceId);
                     }
                 } else {
@@ -966,7 +967,7 @@ class SearchDescription
 
                     Debug::printSQL($sSQL);
 
-                    foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) {
+                    foreach ($oDB->getCol($sSQL) as $iPlaceId) {
                         $aResults[$iPlaceId] = new Result($iPlaceId);
                     }
                 }
index 2d0c7c16d0ae74e2931ba159ba9ffe3818d59085..84dc98d0584fee10558f3271582bcfe4462fd328 100644 (file)
@@ -71,7 +71,7 @@ class TokenList
     /**
      * Add token information from the word table in the database.
      *
-     * @param object   $oDB           Database connection.
+     * @param object   $oDB           Nominatim::DB instance.
      * @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.
@@ -89,7 +89,7 @@ class TokenList
 
         Debug::printSQL($sSQL);
 
-        $aDBWords = chksql($oDB->getAll($sSQL), 'Could not get word tokens.');
+        $aDBWords = $oDB->getAll($sSQL, null, 'Could not get word tokens.');
 
         foreach ($aDBWords as $aWord) {
             $oToken = null;
index 436690696b96c4ee6dbddea0faf9b1dd9793ea98..32fdc8576de70157382e2733f3875a0ac5d728e3 100644 (file)
@@ -120,11 +120,6 @@ function showUsage($aSpec, $bExit = false, $sError = false)
     exit;
 }
 
-function chksql($oSql, $sMsg = false)
-{
-    return $oSql;
-}
-
 function info($sMsg)
 {
     echo date('Y-m-d H:i:s == ').$sMsg."\n";
diff --git a/lib/db.php b/lib/db.php
deleted file mode 100644 (file)
index cac6f2c..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-<?php
-
-namespace Nominatim;
-
-require_once(CONST_BasePath.'/lib/DatabaseError.php');
-
-class DB
-{
-    public $connection;
-
-    public function __construct($sDSN = CONST_Database_DSN)
-    {
-        $this->sDSN = $sDSN;
-    }
-
-    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
-        );
-
-        // 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;
-    }
-}
index 39df4022ce31473c14ba47b08c1c80c00cdb8287..67fb52d1a687d654c87255f4c61371b16b994979 100644 (file)
@@ -10,13 +10,6 @@ require_once(CONST_Debug ? 'DebugHtml.php' : 'DebugNone.php');
  *
  */
 
-
-function chksql($oSql, $sMsg = 'Database request failed')
-{
-    return $oSql;
-}
-
-
 function userError($sMsg)
 {
     throw new Exception($sMsg, 400);
index d21880715abcbe8f91429c2effb973d603de768e..0bd23e31cfe57ffb1376b8025574efd738f22a1e 100644 (file)
@@ -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";
index 920924287342dfb8b83eda50dcfdb299b6b6e862..a399c955ae49a81e50f16d951ad8a22400b104ab 100644 (file)
@@ -53,14 +53,14 @@ class AddressLevelParser
      */
     public function createTable($oDB, $sTable)
     {
-        chksql($oDB->exec('DROP TABLE IF EXISTS '.$sTable));
+        $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->exec($sSql));
+        $oDB->exec($sSql);
 
-        $sSql = 'CREATE UNIQUE INDEX ON '.$sTable.'(country_code, class, type)';
-        chksql($oDB->exec($sSql));
+        $sSql = 'CREATE UNIQUE INDEX ON '.$sTable.' (country_code, class, type)';
+        $oDB->exec($sSql);
 
         $sSql = 'INSERT INTO '.$sTable.' VALUES ';
         foreach ($this->aLevels as $aLevel) {
@@ -93,6 +93,6 @@ class AddressLevelParser
                 }
             }
         }
-        chksql($oDB->exec(rtrim($sSql, ',')));
+        $oDB->exec(rtrim($sSql, ','));
     }
 }
index 9cc00a5f021e9830cd2f2604a0857843277a904a..c14190c3a1be66020216defca9686262ac44f3f0 100755 (executable)
@@ -74,15 +74,9 @@ class SetupFunctions
     public function createDB()
     {
         info('Create DB');
-        $bExists = true;
-        try {
-            $oDB = new \Nominatim\DB;
-            $oDB->connect();
-        } catch (\Nominatim\DatabaseError $e) {
-            $bExists = false;
-        }
+        $oDB = new \Nominatim\DB;
 
-        if ($bExists) {
+        if ($oDB->databaseExists()) {
             fail('database already exists ('.CONST_Database_DSN.')');
         }
 
@@ -122,7 +116,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 = chksql($this->oDB->getOne("select count(*) from pg_proc where proname = 'hstore_to_json'"));
+        $iNumFunc = $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");
@@ -142,7 +136,7 @@ class SetupFunctions
             $this->pgsqlRunScript('ALTER FUNCTION ST_Distance_Spheroid(geometry, geometry, spheroid) RENAME TO ST_DistanceSpheroid');
         }
 
-        $i = chksql($this->oDB->getOne("select count(*) from pg_user where usename = '".CONST_Database_Web_User."'"));
+        $i = $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";
@@ -150,9 +144,7 @@ class SetupFunctions
         }
 
         // Try accessing the C module, so we know early if something is wrong
-        if (!checkModulePresence()) {
-            fail('error loading nominatim.so module');
-        }
+        checkModulePresence(); // raises exception on failure
 
         if (!file_exists(CONST_ExtraDataPath.'/country_osm_grid.sql.gz')) {
             echo 'Error: you need to download the country_osm_grid first:';
@@ -224,7 +216,7 @@ class SetupFunctions
 
         $this->runWithPgEnv($osm2pgsql);
 
-        if (!$this->sIgnoreErrors && !chksql($this->oDB->getRow('select * from place limit 1'))) {
+        if (!$this->sIgnoreErrors && !$this->oDB->getRow('select * from place limit 1')) {
             fail('No Data');
         }
     }
@@ -233,11 +225,9 @@ class SetupFunctions
     {
         info('Create Functions');
 
-        // 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');
-        }
+        // Try accessing the C module, so we know early if something is wrong
+        checkModulePresence(); // raises exception on failure
+
         $this->createSqlFunctions();
     }
 
@@ -386,7 +376,7 @@ class SetupFunctions
         echo '.';
 
         $sSQL = 'select distinct partition from country_name';
-        $aPartitions = chksql($this->oDB->getCol($sSQL));
+        $aPartitions = $this->oDB->getCol($sSQL);
 
         if (!$this->bNoPartitions) $aPartitions[] = 0;
         foreach ($aPartitions as $sPartition) {
@@ -734,7 +724,7 @@ class SetupFunctions
                        );
 
         $aDropTables = array();
-        $aHaveTables = chksql($this->oDB->getCol("SELECT tablename FROM pg_tables WHERE schemaname='public'"));
+        $aHaveTables = $this->oDB->getCol("SELECT tablename FROM pg_tables WHERE schemaname='public'");
 
         foreach ($aHaveTables as $sTable) {
             $bFound = false;
index 89736ae0515c53039403014a3180e9413e09e18d..43f30a090dfff4939f4f511e786e2615d467c1c1 100755 (executable)
@@ -17,8 +17,9 @@ function checkInFile($sOSMFile)
 
 function checkModulePresence()
 {
-    // Try accessing the C module, so we know early if something is wrong
-    // and can simply error out.
+    // Try accessing the C module, so we know early if something is wrong.
+    // Raises Nominatim\DatabaseError on failure
+
     $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";
@@ -26,15 +27,5 @@ function checkModulePresence()
 
     $oDB = new \Nominatim\DB();
     $oDB->connect();
-
-    $bResult = true;
-    try {
-        $oDB->exec($sSQL);
-    } catch (\Nominatim\DatabaseError $e) {
-        echo "\nERROR: Failed to load nominatim module. Reason:\n";
-        echo $oDB->getLastError()[2] . "\n\n";
-        $bResult = false;
-    }
-
-    return $bResult;
+    $oDB->exec($sSQL, null, 'Database server failed to load '.$sModulePath.'/nominatim.so module');
 }
index 01583e5f789499a27a28dbdb4d9e3048c72b761e..9b76efc12f90977a4b91927a75be8e35bb950dc2 100644 (file)
@@ -61,7 +61,7 @@
 
 
     function _one_row($aAddressLine){
-        $bNotUsed = (isset($aAddressLine['isaddress']) && $aAddressLine['isaddress'] == 'f');
+        $bNotUsed = isset($aAddressLine['isaddress']) && !$aAddressLine['isaddress'];
 
         echo '<tr class="' . ($bNotUsed?'notused':'') . '">'."\n";
         echo '  <td class="name">'.(trim($aAddressLine['localname'])?$aAddressLine['localname']:'<span class="noname">No Name</span>')."</td>\n";
                     if ($aPointDetails['calculated_importance']) {
                         kv('Importance'    , $aPointDetails['calculated_importance'].($aPointDetails['importance']?'':' (estimated)') );
                     }
-                    kv('Coverage'        , ($aPointDetails['isarea']=='t'?'Polygon':'Point') );
+                    kv('Coverage'        , ($aPointDetails['isarea']?'Polygon':'Point') );
                     kv('Centre Point'    , $aPointDetails['lat'].','.$aPointDetails['lon'] );
                     kv('OSM'             , osmLink($aPointDetails) );
                     if ($aPointDetails['wikipedia'])
index 06554aba68f2143c6a24b46ce9cdb39e9cfc3362..4afb1b0bc4e717dcd7609d8e5630c6500b566da9 100644 (file)
@@ -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'] == 't');
+$aPlaceDetails['isarea'] = $aPointDetails['isarea'];
 $aPlaceDetails['centroid'] = array(
                               'type' => 'Point',
                               'coordinates' => array( (float) $aPointDetails['lon'], (float) $aPointDetails['lat'] )
index 54e2a8d36d25ab3015cd2cbe4c296359f958676a..d42d9fca36a9e9030856340df0655798c8981490 100644 (file)
@@ -2318,6 +2318,7 @@ DECLARE
   searchhousename HSTORE;
   searchrankaddress INTEGER;
   searchpostcode TEXT;
+  postcode_isaddress BOOL;
   searchclass TEXT;
   searchtype TEXT;
   countryname HSTORE;
@@ -2325,6 +2326,8 @@ 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,
@@ -2441,7 +2444,10 @@ BEGIN
       searchcountrycode := location.country_code;
     END IF;
     IF location.type in ('postcode', 'postal_code') THEN
-      location.isaddress := FALSE;
+      postcode_isaddress := false;
+      IF location.osm_type != 'R' THEN
+        location.isaddress := FALSE;
+      END IF;
     END IF;
     countrylocation := ROW(location.place_id, location.osm_type, location.osm_id,
                            location.name, location.class, location.type,
@@ -2485,7 +2491,7 @@ BEGIN
 
   IF searchpostcode IS NOT NULL THEN
     location := ROW(null, null, null, hstore('ref', searchpostcode), 'place',
-                    'postcode', null, true, true, 5, 0)::addressline;
+                    'postcode', null, false, postcode_isaddress, 5, 0)::addressline;
     RETURN NEXT location;
   END IF;
 
index a50e53cfbd74c9485862ba3688108abf9f05d824..6bab1bc790ba649f7e72e50d0f04b28a0500001e 100644 (file)
@@ -34,3 +34,10 @@ 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
+
index 63c8646946cb2d1170879b17c6ff0a9268340650..e70495f63890f15c958bb75a86ec072963fca68f 100644 (file)
@@ -26,6 +26,18 @@ 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 |
index e7bd18c7653d04570640a0077ba83d56814e2a35..38874c880ec52cb2cc18f684ddf02a89ce8ab820 100644 (file)
@@ -3,10 +3,32 @@
 namespace Nominatim;
 
 require_once(CONST_BasePath.'/lib/lib.php');
-require_once(CONST_BasePath.'/lib/db.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()
     {
@@ -36,9 +58,35 @@ class DBTest extends \PHPUnit\Framework\TestCase
                      throw new \PDOException('ERROR:  syntax error at or near "FROM"');
                  }));
 
-        $oDB = new \Nominatim\DB('');
-        $oDB->connection = $oPDOStub;
-        $oDB->tableExists('abc');
+        $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()
index dbf15fd4875fe5e29e2487ba1d03aa0e71865706..f45e6633bb9cd831ede5cfba76c51dee4b0293ee 100644 (file)
@@ -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');
 
 
index 417f52c09782dbb35a6f95d890ac2902441e7817..d31b219b881ae6a05b4b4a1429ab86d256bd4a75 100644 (file)
@@ -2,8 +2,6 @@
 
 namespace Nominatim;
 
-// require_once(CONST_BasePath.'/lib/db.php');
-// require_once(CONST_BasePath.'/lib/cmd.php');
 require_once(CONST_BasePath.'/lib/TokenList.php');
 
 
index 66b719205705d2b68be4dafc6fbf7c6ccdce9109..8ad96a9524eac81360106412b00c3070ea1458a0 100644 (file)
@@ -84,9 +84,7 @@ if ($aCMDResult['setup-db'] || $aCMDResult['all']) {
 }
 
 // Try accessing the C module, so we know early if something is wrong
-if (!checkModulePresence()) {
-    fail('error loading nominatim.so module');
-}
+checkModulePresence(); // raises exception on failure
 
 if ($aCMDResult['import-data'] || $aCMDResult['all']) {
     $bDidSomething = true;
index e52e3b9bd294fae37a417b18544138a0922f6d2e..2809a198c874b8c9b0a52c6f4758e275a1ecf50d 100644 (file)
@@ -144,7 +144,7 @@ if ($aResult['init-updates']) {
 }
 
 if ($aResult['check-for-updates']) {
-    $aLastState = chksql($oDB->getRow('SELECT sequence_id FROM import_status'));
+    $aLastState = $oDB->getRow('SELECT sequence_id FROM import_status');
 
     if (!$aLastState['sequence_id']) {
         fail('Updates not set up. Please run ./utils/update.php --init-updates.');
@@ -232,13 +232,13 @@ if ($aResult['deduplicate']) {
     }
 
     $sSQL = 'select partition from country_name order by country_code';
-    $aPartitions = chksql($oDB->getCol($sSQL));
+    $aPartitions = $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 = chksql($oDB->getOne($sSQL));
+        $nEntries = $oDB->getOne($sSQL);
         if ($nEntries == 0) {
             unset($aPartitions[$i]);
         }
@@ -247,7 +247,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 = chksql($oDB->getAll($sSQL));
+    $aDuplicateTokens = $oDB->getAll($sSQL);
     foreach ($aDuplicateTokens as $aToken) {
         if (trim($aToken['word_token']) == '' || trim($aToken['word_token']) == '-') continue;
         echo 'Deduping '.$aToken['word_token']."\n";
@@ -255,7 +255,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 = chksql($oDB->getAll($sSQL));
+        $aTokenSet = $oDB->getAll($sSQL);
 
         $aKeep = array_shift($aTokenSet);
         $iKeepID = $aKeep['word_id'];
@@ -265,32 +265,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'].']';
-            chksql($oDB->exec($sSQL));
+            $oDB->exec($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'].']';
-            chksql($oDB->exec($sSQL));
+            $oDB->exec($sSQL);
 
             $sSQL = 'update location_area_country set';
             $sSQL .= ' keywords = array_replace(keywords,'.$aRemove['word_id'].','.$iKeepID.')';
             $sSQL .= ' where keywords @> ARRAY['.$aRemove['word_id'].']';
-            chksql($oDB->exec($sSQL));
+            $oDB->exec($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'].']';
-                chksql($oDB->exec($sSQL));
+                $oDB->exec($sSQL);
 
                 $sSQL = 'update location_area_country set';
                 $sSQL .= ' keywords = array_replace(keywords,'.$aRemove['word_id'].','.$iKeepID.')';
                 $sSQL .= ' where keywords @> ARRAY['.$aRemove['word_id'].']';
-                chksql($oDB->exec($sSQL));
+                $oDB->exec($sSQL);
             }
 
             $sSQL = 'delete from word where word_id = '.$aRemove['word_id'];
-            chksql($oDB->exec($sSQL));
+            $oDB->exec($sSQL);
         }
     }
 }
@@ -341,7 +341,7 @@ if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
 
     while (true) {
         $fStartTime = time();
-        $aLastState = chksql($oDB->getRow('SELECT *, EXTRACT (EPOCH FROM lastimportdate) as unix_ts FROM import_status'));
+        $aLastState = $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";
@@ -353,7 +353,7 @@ if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
         $sBatchEnd = $aLastState['lastimportdate'];
         $iEndSequence = $aLastState['sequence_id'];
 
-        if ($aLastState['indexed'] == 't') {
+        if ($aLastState['indexed']) {
             // Sleep if the update interval has not yet been reached.
             $fNextUpdate = $aLastState['unix_ts'] + CONST_Replication_Update_Interval;
             if ($fNextUpdate > $fStartTime) {
@@ -419,12 +419,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);
-            chksql($oDB->exec($sSQL));
+            $oDB->exec($sSQL);
 
             // update the status
             $sSQL = "UPDATE import_status SET lastimportdate = '$sBatchEnd', indexed=false, sequence_id = $iEndSequence";
             var_Dump($sSQL);
-            chksql($oDB->exec($sSQL));
+            $oDB->exec($sSQL);
             echo date('Y-m-d H:i:s')." Completed download step for $sBatchEnd in ".round((time()-$fCMDStartTime)/60, 2)." minutes\n";
         }
 
index 4904b94c144c3c643dc06760e34001e5d7ecac8d..ac4294bab6d8a293367cb9b6652c5601ce257c7f 100644 (file)
@@ -14,7 +14,7 @@ $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 = chksql($oDB->getAll($sSQL), 'Could not get list of deleted OSM elements.');
+$aPolygons = $oDB->getAll($sSQL, null, 'Could not get list of deleted OSM elements.');
 
 if (CONST_Debug) {
     var_dump($aPolygons);
index c64eaa458f11ce83e86d551af645f7f895880a65..cb371e6b09d2cd8d3e21d463731dce8dea552820 100644 (file)
@@ -31,17 +31,13 @@ $oDB->connect();
 $sLanguagePrefArraySQL = $oDB->getArraySQL($oDB->getDBQuotedList($aLangPrefOrder));
 
 if ($sOsmType && $iOsmId > 0) {
-    $sSQL = sprintf(
-        "SELECT place_id FROM placex WHERE osm_type='%s' AND osm_id=%d",
-        $sOsmType,
-        $iOsmId
-    );
+    $sSQL = 'SELECT place_id FROM placex WHERE osm_type = :type AND osm_id = :id';
     // osm_type and osm_id are not unique enough
     if ($sClass) {
         $sSQL .= " AND class='".$sClass."'";
     }
     $sSQL .= ' ORDER BY class ASC';
-    $sPlaceId = chksql($oDB->getOne($sSQL));
+    $sPlaceId = $oDB->getOne($sSQL, array(':type' => $sOsmType, ':id' => $iOsmId));
 
     // Be nice about our error messages for broken geometry
 
@@ -56,11 +52,11 @@ 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 = '".$sOsmType."'";
-        $sSQL .= '  AND osm_id = '.$iOsmId;
+        $sSQL .= ' WHERE osm_type = :type';
+        $sSQL .= '   AND osm_id = :id';
         $sSQL .= ' ORDER BY updated DESC';
         $sSQL .= ' LIMIT 1';
-        $aPointDetails = chksql($oDB->getRow($sSQL));
+        $aPointDetails = $oDB->getRow($sSQL, array(':type' => $sOsmType, ':id' => $iOsmId));
         if ($aPointDetails) {
             if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches)) {
                 $aPointDetails['error_x'] = $aMatches[1];
@@ -81,20 +77,20 @@ if ($sPlaceId === false) userError('Please select a place id');
 $iPlaceID = (int)$sPlaceId;
 
 if (CONST_Use_US_Tiger_Data) {
-    $iParentPlaceID = chksql($oDB->getOne('SELECT parent_place_id FROM location_property_tiger WHERE place_id = '.$iPlaceID));
+    $iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_tiger WHERE place_id = '.$iPlaceID);
     if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
 }
 
 // interpolated house numbers
-$iParentPlaceID = chksql($oDB->getOne('SELECT parent_place_id FROM location_property_osmline WHERE place_id = '.$iPlaceID));
+$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_osmline WHERE place_id = '.$iPlaceID);
 if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
 
 // artificial postcodes
-$iParentPlaceID = chksql($oDB->getOne('SELECT parent_place_id FROM location_postcode WHERE place_id = '.$iPlaceID));
+$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_postcode WHERE place_id = '.$iPlaceID);
 if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
 
 if (CONST_Use_Aux_Location_data) {
-    $iParentPlaceID = chksql($oDB->getOne('SELECT parent_place_id FROM location_property_aux WHERE place_id = '.$iPlaceID));
+    $iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_aux WHERE place_id = '.$iPlaceID);
     if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
 }
 
@@ -129,7 +125,7 @@ if ($bIncludePolygonAsGeoJSON) {
 $sSQL .= ' FROM placex ';
 $sSQL .= " WHERE place_id = $iPlaceID";
 
-$aPointDetails = chksql($oDB->getRow($sSQL), 'Could not get details of place object.');
+$aPointDetails = $oDB->getRow($sSQL, null, 'Could not get details of place object.');
 
 if (!$aPointDetails) {
     userError('Unknown place id.');
@@ -224,11 +220,17 @@ if ($bIncludeKeywords) {
     $aPlaceSearchName = $oDB->getRow($sSQL);
 
     if (!empty($aPlaceSearchName)) {
-        $sSQL = 'SELECT * FROM word WHERE word_id in ('.substr($aPlaceSearchName['name_vector'], 1, -1).')';
-        $aPlaceSearchNameKeywords = $oDB->getAll($sSQL);
+        $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['nameaddress_vector'], 1, -1).')';
-        $aPlaceSearchAddressKeywords = $oDB->getAll($sSQL);
+        $sWordIds = substr($aPlaceSearchName['nameaddress_vector'], 1, -1);
+        if (!empty($sWordIds)) {
+            $sSQL = 'SELECT * FROM word WHERE word_id in ('.$sWordIds.')';
+            $aPlaceSearchAddressKeywords = $oDB->getAll($sSQL);
+        }
     }
 }
 
@@ -236,7 +238,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 = chksql($oDB->getOne($sSQL));
+    $sDataDate = $oDB->getOne($sSQL);
     $sTileURL = CONST_Map_Tile_URL;
     $sTileAttribution = CONST_Map_Tile_Attribution;
 }
index 2c56b015f3fc7721393c042a8f0617d2ea4f7100..87e8a0afbb258fdaefd03d2169baac6d5522fcbc 100644 (file)
@@ -22,7 +22,7 @@ $oDB->connect();
 $sLanguagePrefArraySQL = $oDB->getArraySQL($oDB->getDBQuotedList($aLangPrefOrder));
 
 if ($sOsmType && $iOsmId > 0) {
-    $sPlaceId = chksql($oDB->getOne("select place_id from placex where osm_type = '".$sOsmType."' and osm_id = ".$iOsmId." order by type = 'postcode' asc"));
+    $sPlaceId = $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 +31,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 = chksql($oDB->getRow($sSQL));
+        $aPointDetails = $oDB->getRow($sSQL);
         if ($aPointDetails) {
             if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches)) {
                 $aPointDetails['error_x'] = $aMatches[1];
@@ -48,12 +48,12 @@ if (!$sPlaceId) userError('Please select a place id');
 $iPlaceID = (int)$sPlaceId;
 
 if (CONST_Use_US_Tiger_Data) {
-    $iParentPlaceID = chksql($oDB->getOne('select parent_place_id from location_property_tiger where place_id = '.$iPlaceID));
+    $iParentPlaceID = $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 = chksql($oDB->getOne('select parent_place_id from location_property_aux where place_id = '.$iPlaceID));
+    $iParentPlaceID = $oDB->getOne('select parent_place_id from location_property_aux where place_id = '.$iPlaceID);
     if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
 }
 
@@ -89,7 +89,7 @@ if ($sOutputFormat == 'json') {
     exit;
 }
 
-$aRelatedPlaceIDs = chksql($oDB->getCol($sSQL = "select place_id from placex where linked_place_id = $iPlaceID or place_id = $iPlaceID"));
+$aRelatedPlaceIDs = $oDB->getCol("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 +97,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 = chksql($oDB->getAll($sSQL));
+$aParentOfLines = $oDB->getAll($sSQL);
 
 if (!empty($aParentOfLines)) {
     echo '<h2>Parent Of:</h2>';
@@ -121,7 +121,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']=='t'?'Polygon':'Point').'</span>';
+            echo '<span class="area">'.($aAddressLine['isarea']?'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'];
index 00e043bdaf3cef6642a7dd6d01be6b3d011fa24f..a2264b18c46eaca0e12ad6299b060b062d58635b 100644 (file)
@@ -15,7 +15,7 @@ $sClass = $oParams->getString('class', false);
 $oDB = new Nominatim\DB();
 $oDB->connect();
 
-$iTotalBroken = (int) chksql($oDB->getOne('select count(*) from import_polygon_error'));
+$iTotalBroken = (int) $oDB->getOne('select count(*) from import_polygon_error');
 
 $aPolygons = array();
 while ($iTotalBroken && empty($aPolygons)) {
@@ -37,7 +37,7 @@ while ($iTotalBroken && empty($aPolygons)) {
     }
 
     $sSQL .= ' order by updated desc limit 1000';
-    $aPolygons = chksql($oDB->getAll($sSQL));
+    $aPolygons = $oDB->getAll($sSQL);
 }
 
 if (CONST_Debug) {
index e1a1b672ad928d82a11e05ad11217c98ef10c4ad..7b9ef3b3b264c71e5ae894f3e5348a49be9ea84a 100644 (file)
@@ -75,13 +75,16 @@ if (CONST_Debug) {
 }
 
 if ($sOutputFormat == 'html') {
-    $sDataDate = chksql($oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1"));
+    $sDataDate = $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 = chksql($oDB->getOne('SELECT ST_Distance(ST_SetSRID(ST_Point('.$fLon.','.$fLat.'),4326), centroid) FROM placex where place_id='.$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'])
+        );
     }
 }
 
index a9bb3f0b0d381cbef5f9f325330317c6b4b2c35b..26c10122924dc9329ea288d06a40687d75a33dfc 100644 (file)
@@ -66,7 +66,7 @@ $hLog = logStart($oDB, 'search', $oGeocode->getQueryString(), $aLangPrefOrder);
 $aSearchResults = $oGeocode->lookup();
 
 if ($sOutputFormat=='html') {
-    $sDataDate = chksql($oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1"));
+    $sDataDate = $oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1");
 }
 logEnd($oDB, $hLog, count($aSearchResults));