Thomas Bruederli
2013-10-07 120db629b0645033fd6a477b9f96cc8dad589213
commit | author | age
0d94fd 1 <?php
AM 2
3d231c 3 /**
0d94fd 4  +-----------------------------------------------------------------------+
AM 5  | This file is part of the Roundcube Webmail client                     |
6  | Copyright (C) 2005-2012, The Roundcube Dev Team                       |
7  |                                                                       |
8  | Licensed under the GNU General Public License version 3 or            |
9  | any later version with exceptions for skins & plugins.                |
10  | See the README file for a full license statement.                     |
11  |                                                                       |
12  | PURPOSE:                                                              |
13  |   Database wrapper class that implements PHP PDO functions            |
14  |   for MySQL database                                                  |
15  +-----------------------------------------------------------------------+
16  | Author: Aleksander Machniak <alec@alec.pl>                            |
17  +-----------------------------------------------------------------------+
18 */
19
20 /**
21  * Database independent query interface
22  *
23  * This is a wrapper for the PHP PDO
24  *
9ab346 25  * @package    Framework
AM 26  * @subpackage Database
0d94fd 27  */
AM 28 class rcube_db_mysql extends rcube_db
29 {
88107d 30     public $db_provider = 'mysql';
TB 31
8c2375 32     /**
d18640 33      * Object constructor
AM 34      *
35      * @param string $db_dsnw DSN for read/write operations
36      * @param string $db_dsnr Optional DSN for read only operations
37      * @param bool   $pconn   Enables persistent connections
8c2375 38      */
d18640 39     public function __construct($db_dsnw, $db_dsnr = '', $pconn = false)
0d94fd 40     {
52b256 41         if (version_compare(PHP_VERSION, '5.3.0', '<')) {
AM 42             rcube::raise_error(array('code' => 600, 'type' => 'db',
43                 'line' => __LINE__, 'file' => __FILE__,
44                 'message' => "MySQL driver requires PHP >= 5.3, current version is " . PHP_VERSION),
45                 true, true);
46         }
47
d18640 48         parent::__construct($db_dsnw, $db_dsnr, $pconn);
AM 49
0d94fd 50         // SQL identifiers quoting
AM 51         $this->options['identifier_start'] = '`';
52         $this->options['identifier_end'] = '`';
53     }
54
55     /**
d18640 56      * Driver-specific configuration of database connection
AM 57      *
58      * @param array $dsn DSN for DB connections
59      * @param PDO   $dbh Connection handler
60      */
61     protected function conn_configure($dsn, $dbh)
62     {
120db6 63         $dbh->query("SET NAMES 'utf8'");
d18640 64     }
AM 65
66     /**
0d94fd 67      * Abstract SQL statement for value concatenation
AM 68      *
69      * @return string SQL statement to be used in query
70      */
71     public function concat(/* col1, col2, ... */)
72     {
73         $args = func_get_args();
74
75         if (is_array($args[0])) {
76             $args = $args[0];
77         }
78
79         return 'CONCAT(' . join(', ', $args) . ')';
80     }
81
82     /**
8c2375 83      * Returns PDO DSN string from DSN array
c2b20f 84      *
AM 85      * @param array $dsn DSN parameters
86      *
87      * @return string Connection string
0d94fd 88      */
AM 89     protected function dsn_string($dsn)
90     {
91         $params = array();
92         $result = 'mysql:';
93
94         if ($dsn['database']) {
95             $params[] = 'dbname=' . $dsn['database'];
96         }
97
98         if ($dsn['hostspec']) {
99             $params[] = 'host=' . $dsn['hostspec'];
100         }
101
102         if ($dsn['port']) {
103             $params[] = 'port=' . $dsn['port'];
104         }
105
106         if ($dsn['socket']) {
107             $params[] = 'unix_socket=' . $dsn['socket'];
108         }
109
110         $params[] = 'charset=utf8';
111
112         if (!empty($params)) {
113             $result .= implode(';', $params);
114         }
115
116         return $result;
117     }
118
c389a8 119     /**
c2b20f 120      * Returns driver-specific connection options
AM 121      *
122      * @param array $dsn DSN parameters
123      *
124      * @return array Connection options
125      */
126     protected function dsn_options($dsn)
127     {
128         $result = array();
129
130         if (!empty($dsn['key'])) {
131             $result[PDO::MYSQL_ATTR_KEY] = $dsn['key'];
132         }
133
134         if (!empty($dsn['cipher'])) {
135             $result[PDO::MYSQL_ATTR_CIPHER] = $dsn['cipher'];
136         }
137
138         if (!empty($dsn['cert'])) {
139             $result[PDO::MYSQL_ATTR_SSL_CERT] = $dsn['cert'];
140         }
141
142         if (!empty($dsn['capath'])) {
143             $result[PDO::MYSQL_ATTR_SSL_CAPATH] = $dsn['capath'];
144         }
145
146         if (!empty($dsn['ca'])) {
147             $result[PDO::MYSQL_ATTR_SSL_CA] = $dsn['ca'];
148         }
149
f6cd73 150         // Always return matching (not affected only) rows count
AM 151         $result[PDO::MYSQL_ATTR_FOUND_ROWS] = true;
152
f96593 153         // Enable AUTOCOMMIT mode (#1488902)
3725cf 154         $result[PDO::ATTR_AUTOCOMMIT] = true;
f96593 155
c2b20f 156         return $result;
AM 157     }
158
159     /**
c389a8 160      * Get database runtime variables
AM 161      *
3d231c 162      * @param string $varname Variable name
AM 163      * @param mixed  $default Default value if variable is not set
c389a8 164      *
AM 165      * @return mixed Variable value or default
166      */
167     public function get_variable($varname, $default = null)
168     {
169         if (!isset($this->variables)) {
170             $this->variables = array();
171
172             $result = $this->query('SHOW VARIABLES');
173
c027ba 174             while ($row = $this->fetch_array($result)) {
c389a8 175                 $this->variables[$row[0]] = $row[1];
AM 176             }
177         }
178
179         return isset($this->variables[$varname]) ? $this->variables[$varname] : $default;
180     }
181
0ee22c 182     /**
TB 183      * Handle DB errors, re-issue the query on deadlock errors from InnoDB row-level locking
184      *
185      * @param string Query that triggered the error
186      * @return mixed Result to be stored and returned
187      */
188     protected function handle_error($query)
189     {
190         $error = $this->dbh->errorInfo();
191
192         // retry after "Deadlock found when trying to get lock" errors
193         $retries = 2;
194         while ($error[1] == 1213 && $retries >= 0) {
195             usleep(50000);  // wait 50 ms
196             $result = $this->dbh->query($query);
197             if ($result !== false) {
198                 return $result;
199             }
200             $error = $this->dbh->errorInfo();
201             $retries--;
202         }
203
204         return parent::handle_error($query);
205     }
206
0d94fd 207 }