5 * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * * Neither the name of Sebastian Bergmann nor the names of his
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
40 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @link http://www.phpunit.de/
44 * @since File available since Release 3.1.4
47 require_once 'PHPUnit/Util/Filter.php';
49 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
56 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
57 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
58 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
59 * @version Release: 3.3.17
60 * @link http://www.phpunit.de/
61 * @since Class available since Release 3.1.4
63 class PHPUnit_Util_PDO
65 public static function factory($dsn)
67 $parsed = self::parseDSN($dsn);
69 switch ($parsed['phptype']) {
78 $driverOptions = NULL;
80 foreach ( $parsed as $key => $val )
117 $driverOptions = $val;
122 if ( !isset( $database ) )
124 throw new InvalidArgumentException('Invalid DSN.');
127 $dsn = "mysql:dbname=$database";
129 if ( isset( $host ) && $host )
131 $dsn .= ";host=$host";
134 if ( isset( $port ) && $port )
136 $dsn .= ";port=$port";
139 if ( isset( $charset ) && $charset )
141 $dsn .= ";charset=$charset";
144 if ( isset( $socket ) && $socket )
146 $dsn .= ";unix_socket=$socket";
149 $dbh = new PDO($dsn, $user, $pass, $driverOptions);
154 $dbh = new PDO($dsn);
159 throw new InvalidArgumentException('Invalid DSN.');
163 $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
169 * Returns the Data Source Name as a structure containing the various parts of the DSN.
171 * Additional keys can be added by appending a URI query string to the
174 * The format of the supplied DSN is in its fullest form:
176 * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
179 * Most variations are allowed:
181 * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
182 * phptype://username:password@hostspec/database_name
183 * phptype://username:password@hostspec
184 * phptype://username@hostspec
185 * phptype://hostspec/database
191 * This function is 'borrowed' from PEAR /DB.php .
193 * @param string $dsn Data Source Name to be parsed
195 * @return array an associative array with the following keys:
196 * + phptype: Database backend used in PHP (mysql, odbc etc.)
197 * + dbsyntax: Database used with regards to SQL syntax etc.
198 * + protocol: Communication protocol to use (tcp, unix etc.)
199 * + hostspec: Host specification (hostname[:port])
200 * + database: Database to use on the DBMS server
201 * + username: User name for login
202 * + password: Password for login
204 public static function parseDSN( $dsn )
218 if ( is_array( $dsn ) )
220 $dsn = array_merge( $parsed, $dsn );
221 if ( !$dsn['dbsyntax'] )
223 $dsn['dbsyntax'] = $dsn['phptype'];
228 // Find phptype and dbsyntax
229 if ( ( $pos = strpos( $dsn, '://' ) ) !== FALSE )
231 $str = substr( $dsn, 0, $pos );
232 $dsn = substr( $dsn, $pos + 3 );
240 // Get phptype and dbsyntax
241 // $str => phptype(dbsyntax)
242 if ( preg_match( '|^(.+?)\((.*?)\)$|', $str, $arr ) )
244 $parsed['phptype'] = $arr[1];
245 $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
249 $parsed['phptype'] = $str;
250 $parsed['dbsyntax'] = $str;
253 if ( !count( $dsn ) )
258 // Get (if found): username and password
259 // $dsn => username:password@protocol+hostspec/database
260 if ( ( $at = strrpos( (string) $dsn, '@' ) ) !== FALSE )
262 $str = substr( $dsn, 0, $at );
263 $dsn = substr( $dsn, $at + 1 );
264 if ( ( $pos = strpos( $str, ':' ) ) !== FALSE )
266 $parsed['username'] = rawurldecode( substr( $str, 0, $pos ) );
267 $parsed['password'] = rawurldecode( substr( $str, $pos + 1 ) );
271 $parsed['username'] = rawurldecode( $str );
275 // Find protocol and hostspec
277 if ( preg_match( '|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match ) )
279 // $dsn => proto(proto_opts)/database
281 $proto_opts = $match[2] ? $match[2] : FALSE;
286 // $dsn => protocol+hostspec/database (old format)
287 if ( strpos( $dsn, '+' ) !== FALSE )
289 list( $proto, $dsn ) = explode( '+', $dsn, 2 );
291 if ( strpos( $dsn, '/' ) !== FALSE )
293 list( $proto_opts, $dsn ) = explode( '/', $dsn, 2 );
302 // process the different protocol options
303 $parsed['protocol'] = ( !empty( $proto ) ) ? $proto : 'tcp';
304 $proto_opts = rawurldecode( $proto_opts );
305 if ( $parsed['protocol'] == 'tcp' )
307 if ( strpos( $proto_opts, ':' ) !== FALSE )
309 list( $parsed['hostspec'], $parsed['port'] ) = explode( ':', $proto_opts );
313 $parsed['hostspec'] = $proto_opts;
316 elseif ( $parsed['protocol'] == 'unix' )
318 $parsed['socket'] = $proto_opts;
325 if ( ( $pos = strpos( $dsn, '?' ) ) === FALSE )
328 $parsed['database'] = rawurldecode( $dsn );
332 // /database?param1=value1¶m2=value2
333 $parsed['database'] = rawurldecode( substr( $dsn, 0, $pos ) );
334 $dsn = substr( $dsn, $pos + 1 );
335 if ( strpos( $dsn, '&') !== FALSE )
337 $opts = explode( '&', $dsn );
340 { // database?param1=value1
341 $opts = array( $dsn );
343 foreach ( $opts as $opt )
345 list( $key, $value ) = explode( '=', $opt );
346 if ( !isset( $parsed[$key] ) )
348 // don't allow params overwrite
349 $parsed[$key] = rawurldecode( $value );