]> git.openstreetmap.org Git - nominatim.git/blob - lib/db.php
replace database abstraction DB with PDO
[nominatim.git] / lib / db.php
1 <?php
2
3 namespace Nominatim;
4
5 require_once(CONST_BasePath.'/lib/DatabaseError.php');
6
7 class DB
8 {
9     public $connection;
10
11     public function __construct($sDSN = CONST_Database_DSN)
12     {
13         $this->sDSN = $sDSN;
14     }
15
16     public function connect($bNew = false, $bPersistent = true)
17     {
18         $aConnOptions = array(
19                          \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
20                          \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
21                          \PDO::ATTR_PERSISTENT         => $bPersistent
22         );
23
24         // https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
25         try {
26             $conn = new \PDO($this->sDSN, null, null, $aConnOptions);
27         } catch (\PDOException $e) {
28             $sMsg = 'Failed to establish database connection:' . $e->getMessage();
29             throw new \Nominatim\DatabaseError($sMsg, 500, null, $e->getMessage());
30         }
31
32         $conn->exec("SET DateStyle TO 'sql,european'");
33         $conn->exec("SET client_encoding TO 'utf-8'");
34         $iMaxExecution = ini_get('max_execution_time');
35         if ($iMaxExecution > 0) $conn->setAttribute(\PDO::ATTR_TIMEOUT, $iMaxExecution); // seconds
36
37         $this->connection = $conn;
38         return true;
39     }
40
41     // returns the number of rows that were modified or deleted by the SQL
42     // statement. If no rows were affected returns 0.
43     public function exec($sSQL)
44     {
45         $val = null;
46         try {
47             $val = $this->connection->exec($sSQL);
48         } catch (\PDOException $e) {
49             throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
50         }
51         return $val;
52     }
53
54     public function getRow($sSQL)
55     {
56         try {
57             $stmt = $this->connection->query($sSQL);
58             $row = $stmt->fetch();
59         } catch (\PDOException $e) {
60             throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
61         }
62         return $row;
63     }
64
65     public function getOne($sSQL)
66     {
67         try {
68             $stmt = $this->connection->query($sSQL);
69             $row = $stmt->fetch(\PDO::FETCH_NUM);
70             if ($row === false) return false;
71         } catch (\PDOException $e) {
72             throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
73         }
74         return $row[0];
75     }
76
77     public function getAll($sSQL)
78     {
79         try {
80             $stmt = $this->connection->query($sSQL);
81             $rows = $stmt->fetchAll();
82         } catch (\PDOException $e) {
83             throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
84         }
85         return $rows;
86     }
87
88     public function getCol($sSQL)
89     {
90         $aVals = array();
91         try {
92             $stmt = $this->connection->query($sSQL);
93             while ($val = $stmt->fetchColumn(0)) { // returns first column or false
94                 $aVals[] = $val;
95             }
96         } catch (\PDOException $e) {
97             throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
98         }
99         return $aVals;
100     }
101
102     public function getAssoc($sSQL)
103     {
104         try {
105             $stmt = $this->connection->query($sSQL);
106             $aList = array();
107             while ($aRow = $stmt->fetch(\PDO::FETCH_NUM)) {
108                 $aList[$aRow[0]] = $aRow[1];
109             }
110         } catch (\PDOException $e) {
111             throw new \Nominatim\DatabaseError('Database query failed', 500, null, $e, $sSQL);
112         }
113         return $aList;
114     }
115
116
117     // St. John's Way => 'St. John\'s Way'
118     public function getDBQuoted($sVal)
119     {
120         return $this->connection->quote($sVal);
121     }
122
123     public function getDBQuotedList($aVals)
124     {
125         return array_map(function ($sVal) {
126             return $this->getDBQuoted($sVal);
127         }, $aVals);
128     }
129
130     public function getArraySQL($a)
131     {
132         return 'ARRAY['.join(',', $a).']';
133     }
134
135     public function getLastError()
136     {
137         // https://secure.php.net/manual/en/pdo.errorinfo.php
138         return $this->connection->errorInfo();
139     }
140
141     public function tableExists($sTableName)
142     {
143         $sSQL = 'SELECT count(*) FROM pg_tables WHERE tablename = '.$this->getDBQuoted($sTableName);
144         return ($this->getOne($sSQL) == 1);
145     }
146
147     public function getPostgresVersion()
148     {
149         $sVersionString = $this->getOne('SHOW server_version_num');
150         preg_match('#([0-9]?[0-9])([0-9][0-9])[0-9][0-9]#', $sVersionString, $aMatches);
151         return (float) ($aMatches[1].'.'.$aMatches[2]);
152     }
153
154     public function getPostgisVersion()
155     {
156         $sVersionString = $this->getOne('select postgis_lib_version()');
157         preg_match('#^([0-9]+)[.]([0-9]+)[.]#', $sVersionString, $aMatches);
158         return (float) ($aMatches[1].'.'.$aMatches[2]);
159     }
160
161     public static function parseDSN($sDSN)
162     {
163         // https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
164         $aInfo = array();
165         if (preg_match('/^pgsql:(.+)/', $sDSN, $aMatches)) {
166             foreach (explode(';', $aMatches[1]) as $sKeyVal) {
167                 list($sKey, $sVal) = explode('=', $sKeyVal, 2);
168                 if ($sKey == 'host') $sKey = 'hostspec';
169                 if ($sKey == 'dbname') $sKey = 'database';
170                 if ($sKey == 'user') $sKey = 'username';
171                 $aInfo[$sKey] = $sVal;
172             }
173         }
174         return $aInfo;
175     }
176 }