]> git.openstreetmap.org Git - nominatim.git/blobdiff - lib/DB.php
Merge pull request #1899 from mtmail/use-new-dsn-format-in-vagrant-md
[nominatim.git] / lib / DB.php
index ddc0932c871e123214e3d373b7a33e9abcaa193a..38b3e27ec8102f5ce8daca912a263ee62a311a3d 100644 (file)
@@ -135,7 +135,7 @@ class DB
         try {
             $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
 
         try {
             $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
 
-            while ($val = $stmt->fetchColumn(0)) { // returns first column or false
+            while (($val = $stmt->fetchColumn(0)) !== false) { // returns first column or false
                 $aVals[] = $val;
             }
         } catch (\PDOException $e) {
                 $aVals[] = $val;
             }
         } catch (\PDOException $e) {
@@ -241,11 +241,103 @@ class DB
     }
 
     /**
     }
 
     /**
-     * Since the DSN includes the database name, checks if the connection works.
+    * Returns a list of table names in the database
+    *
+    * @return array[]
+    */
+    public function getListOfTables()
+    {
+        return $this->getCol("SELECT tablename FROM pg_tables WHERE schemaname='public'");
+    }
+
+    /**
+     * Deletes a table. Returns true if deleted or didn't exist.
+     *
+     * @param string  $sTableName
      *
      * @return boolean
      */
      *
      * @return boolean
      */
-    public function databaseExists()
+    public function deleteTable($sTableName)
+    {
+        return $this->exec('DROP TABLE IF EXISTS '.$sTableName.' CASCADE') == 0;
+    }
+
+    /**
+    * 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;
+    }
+
+    /**
+     * Tries to connect to the database but on failure doesn't throw an exception.
+     *
+     * @return boolean
+     */
+    public function checkConnection()
     {
         $bExists = true;
         try {
     {
         $bExists = true;
         try {
@@ -280,6 +372,13 @@ class DB
         return (float) ($aMatches[1].'.'.$aMatches[2]);
     }
 
         return (float) ($aMatches[1].'.'.$aMatches[2]);
     }
 
+    /**
+     * Returns an associate array of postgresql database connection settings. Keys can
+     * be 'database', 'hostspec', 'port', 'username', 'password'.
+     * Returns empty array on failure, thus check if at least 'database' is set.
+     *
+     * @return array[]
+     */
     public static function parseDSN($sDSN)
     {
         // https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
     public static function parseDSN($sDSN)
     {
         // https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
@@ -295,4 +394,28 @@ class DB
         }
         return $aInfo;
     }
         }
         return $aInfo;
     }
+
+    /**
+     * Takes an array of settings and return the DNS string. Key names can be
+     * 'database', 'hostspec', 'port', 'username', 'password' but aliases
+     * 'dbname', 'host' and 'user' are also supported.
+     *
+     * @return string
+     *
+     */
+    public static function generateDSN($aInfo)
+    {
+        $sDSN = sprintf(
+            'pgsql:host=%s;port=%s;dbname=%s;user=%s;password=%s;',
+            $aInfo['host'] ?? $aInfo['hostspec'] ?? '',
+            $aInfo['port'] ?? '',
+            $aInfo['dbname'] ?? $aInfo['database'] ?? '',
+            $aInfo['user'] ?? '',
+            $aInfo['password'] ?? ''
+        );
+        $sDSN = preg_replace('/\b\w+=;/', '', $sDSN);
+        $sDSN = preg_replace('/;\Z/', '', $sDSN);
+
+        return $sDSN;
+    }
 }
 }