5,7 → 5,7 |
/** |
* Database independent query interface |
* |
* PHP versions 4 and 5 |
* PHP version 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
18,9 → 18,9 |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2005 The PHP Group |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id: DB.php,v 1.80 2005/02/16 02:16:00 danielc Exp $ |
* @version CVS: $Id$ |
* @link http://pear.php.net/package/DB |
*/ |
|
424,14 → 424,14 |
* @author Stig Bakken <ssb@php.net> |
* @author Tomas V.V.Cox <cox@idecnet.com> |
* @author Daniel Convissor <danielc@php.net> |
* @copyright 1997-2005 The PHP Group |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.7.6 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB |
{ |
// {{{ &factory() |
// {{{ factory() |
|
/** |
* Create a new DB object for the specified database type but don't |
444,7 → 444,7 |
* |
* @see DB_common::setOption() |
*/ |
function &factory($type, $options = false) |
public static function factory($type, $options = false) |
{ |
if (!is_array($options)) { |
$options = array('persistent' => $options); |
467,7 → 467,7 |
return $tmp; |
} |
|
@$obj =& new $classname; |
@$obj = new $classname; |
|
foreach ($options as $option => $value) { |
$test = $obj->setOption($option, $value); |
480,7 → 480,7 |
} |
|
// }}} |
// {{{ &connect() |
// {{{ connect() |
|
/** |
* Create a new DB object including a connection to the specified database |
495,7 → 495,7 |
* 'portability' => DB_PORTABILITY_ALL, |
* ); |
* |
* $db =& DB::connect($dsn, $options); |
* $db = DB::connect($dsn, $options); |
* if (PEAR::isError($db)) { |
* die($db->getMessage()); |
* } |
515,7 → 515,7 |
* |
* @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError() |
*/ |
function &connect($dsn, $options = array()) |
public static function connect($dsn, $options = array()) |
{ |
$dsninfo = DB::parseDSN($dsn); |
$type = $dsninfo['phptype']; |
539,12 → 539,13 |
if (!class_exists($classname)) { |
$tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, |
"Unable to include the DB/{$type}.php" |
. " file for '$dsn'", |
. " file for '" |
. DB::getDSNString($dsn, true) . "'", |
'DB_Error', true); |
return $tmp; |
} |
|
@$obj =& new $classname; |
@$obj = new $classname; |
|
foreach ($options as $option => $value) { |
$test = $obj->setOption($option, $value); |
555,7 → 556,11 |
|
$err = $obj->connect($dsninfo, $obj->getOption('persistent')); |
if (DB::isError($err)) { |
$err->addUserInfo($dsn); |
if (is_array($dsn)) { |
$err->addUserInfo(DB::getDSNString($dsn, true)); |
} else { |
$err->addUserInfo($dsn); |
} |
return $err; |
} |
|
572,7 → 577,7 |
*/ |
function apiVersion() |
{ |
return '1.7.6'; |
return '1.9.2'; |
} |
|
// }}} |
585,9 → 590,9 |
* |
* @return bool whether $value is DB_Error object |
*/ |
function isError($value) |
public static function isError($value) |
{ |
return is_a($value, 'DB_Error'); |
return is_object($value) && is_a($value, 'DB_Error'); |
} |
|
// }}} |
600,7 → 605,7 |
* |
* @return bool whether $value is a DB_<driver> object |
*/ |
function isConnection($value) |
public static function isConnection($value) |
{ |
return (is_object($value) && |
is_subclass_of($value, 'db_common') && |
621,11 → 626,11 |
* |
* @return boolean whether $query is a data manipulation query |
*/ |
function isManip($query) |
public static function isManip($query) |
{ |
$manips = 'INSERT|UPDATE|DELETE|REPLACE|' |
. 'CREATE|DROP|' |
. 'LOAD DATA|SELECT .* INTO|COPY|' |
. 'LOAD DATA|SELECT .* INTO .* FROM|COPY|' |
. 'ALTER|GRANT|REVOKE|' |
. 'LOCK|UNLOCK'; |
if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) { |
645,7 → 650,7 |
* @return string the error message or false if the error code was |
* not recognized |
*/ |
function errorMessage($value) |
public static function errorMessage($value) |
{ |
static $errorMessages; |
if (!isset($errorMessages)) { |
726,7 → 731,7 |
* + username: User name for login |
* + password: Password for login |
*/ |
function parseDSN($dsn) |
public static function parseDSN($dsn) |
{ |
$parsed = array( |
'phptype' => false, |
808,13 → 813,11 |
// process the different protocol options |
$parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp'; |
$proto_opts = rawurldecode($proto_opts); |
if (strpos($proto_opts, ':') !== false) { |
list($proto_opts, $parsed['port']) = explode(':', $proto_opts); |
} |
if ($parsed['protocol'] == 'tcp') { |
if (strpos($proto_opts, ':') !== false) { |
list($parsed['hostspec'], |
$parsed['port']) = explode(':', $proto_opts); |
} else { |
$parsed['hostspec'] = $proto_opts; |
} |
$parsed['hostspec'] = $proto_opts; |
} elseif ($parsed['protocol'] == 'unix') { |
$parsed['socket'] = $proto_opts; |
} |
848,6 → 851,82 |
} |
|
// }}} |
// {{{ getDSNString() |
|
/** |
* Returns the given DSN in a string format suitable for output. |
* |
* @param array|string the DSN to parse and format |
* @param boolean true to hide the password, false to include it |
* @return string |
*/ |
public static function getDSNString($dsn, $hidePassword) { |
/* Calling parseDSN will ensure that we have all the array elements |
* defined, and means that we deal with strings and array in the same |
* manner. */ |
$dsnArray = DB::parseDSN($dsn); |
|
if ($hidePassword) { |
$dsnArray['password'] = 'PASSWORD'; |
} |
|
/* Protocol is special-cased, as using the default "tcp" along with an |
* Oracle TNS connection string fails. */ |
if (is_string($dsn) && strpos($dsn, 'tcp') === false && $dsnArray['protocol'] == 'tcp') { |
$dsnArray['protocol'] = false; |
} |
|
// Now we just have to construct the actual string. This is ugly. |
$dsnString = $dsnArray['phptype']; |
if ($dsnArray['dbsyntax']) { |
$dsnString .= '('.$dsnArray['dbsyntax'].')'; |
} |
$dsnString .= '://' |
.$dsnArray['username'] |
.':' |
.$dsnArray['password'] |
.'@' |
.$dsnArray['protocol']; |
if ($dsnArray['socket']) { |
$dsnString .= '('.$dsnArray['socket'].')'; |
} |
if ($dsnArray['protocol'] && $dsnArray['hostspec']) { |
$dsnString .= '+'; |
} |
$dsnString .= $dsnArray['hostspec']; |
if ($dsnArray['port']) { |
$dsnString .= ':'.$dsnArray['port']; |
} |
$dsnString .= '/'.$dsnArray['database']; |
|
/* Option handling. Unfortunately, parseDSN simply places options into |
* the top-level array, so we'll first get rid of the fields defined by |
* DB and see what's left. */ |
unset($dsnArray['phptype'], |
$dsnArray['dbsyntax'], |
$dsnArray['username'], |
$dsnArray['password'], |
$dsnArray['protocol'], |
$dsnArray['socket'], |
$dsnArray['hostspec'], |
$dsnArray['port'], |
$dsnArray['database'] |
); |
if (count($dsnArray) > 0) { |
$dsnString .= '?'; |
$i = 0; |
foreach ($dsnArray as $key => $value) { |
if (++$i > 1) { |
$dsnString .= '&'; |
} |
$dsnString .= $key.'='.$value; |
} |
} |
|
return $dsnString; |
} |
|
// }}} |
} |
|
// }}} |
860,9 → 939,9 |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @copyright 1997-2005 The PHP Group |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.7.6 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_Error extends PEAR_Error |
880,18 → 959,32 |
* |
* @see PEAR_Error |
*/ |
function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN, |
function __construct($code = DB_ERROR, $mode = PEAR_ERROR_RETURN, |
$level = E_USER_NOTICE, $debuginfo = null) |
{ |
if (is_int($code)) { |
$this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code, |
parent::__construct('DB Error: ' . DB::errorMessage($code), $code, |
$mode, $level, $debuginfo); |
} else { |
$this->PEAR_Error("DB Error: $code", DB_ERROR, |
parent::__construct("DB Error: $code", DB_ERROR, |
$mode, $level, $debuginfo); |
} |
} |
|
/** |
* Workaround to both avoid the "Redefining already defined constructor" |
* PHP error and provide backward compatibility in case someone is calling |
* DB_Error() dynamically |
*/ |
public function __call($method, $arguments) |
{ |
if ($method == 'DB_Error') { |
return call_user_func_array(array($this, '__construct'), $arguments); |
} |
trigger_error( |
'Call to undefined method DB_Error::' . $method . '()', E_USER_ERROR |
); |
} |
// }}} |
} |
|
907,9 → 1000,9 |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @copyright 1997-2005 The PHP Group |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.7.6 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
*/ |
class DB_result |
1016,7 → 1109,7 |
* |
* @return void |
*/ |
function DB_result(&$dbh, $result, $options = array()) |
function __construct(&$dbh, $result, $options = array()) |
{ |
$this->autofree = $dbh->options['autofree']; |
$this->dbh = &$dbh; |
1089,7 → 1182,7 |
$fetchmode = DB_FETCHMODE_ASSOC; |
$object_class = $this->fetchmode_object_class; |
} |
if ($this->limit_from !== null) { |
if (is_null($rownum) && $this->limit_from !== null) { |
if ($this->row_counter === null) { |
$this->row_counter = $this->limit_from; |
// Skip rows |
1121,7 → 1214,7 |
if ($object_class == 'stdClass') { |
$arr = (object) $arr; |
} else { |
$arr = &new $object_class($arr); |
$arr = new $object_class($arr); |
} |
} |
return $arr; |
1171,7 → 1264,7 |
$fetchmode = DB_FETCHMODE_ASSOC; |
$object_class = $this->fetchmode_object_class; |
} |
if ($this->limit_from !== null) { |
if (is_null($rownum) && $this->limit_from !== null) { |
if ($this->row_counter === null) { |
$this->row_counter = $this->limit_from; |
// Skip rows |
1253,10 → 1346,33 |
while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) { |
$i++; |
} |
return $i; |
$count = $i; |
} else { |
return $this->dbh->numRows($this->result); |
$count = $this->dbh->numRows($this->result); |
} |
|
/* fbsql is checked for here because limit queries are implemented |
* using a TOP() function, which results in fbsql_num_rows still |
* returning the total number of rows that would have been returned, |
* rather than the real number. As a result, we'll just do the limit |
* calculations for fbsql in the same way as a database with emulated |
* limits. Unfortunately, we can't just do this in DB_fbsql::numRows() |
* because that only gets the result resource, rather than the full |
* DB_Result object. */ |
if (($this->dbh->features['limit'] === 'emulate' |
&& $this->limit_from !== null) |
|| $this->dbh->phptype == 'fbsql') { |
$limit_count = is_null($this->limit_count) ? $count : $this->limit_count; |
if ($count < $this->limit_from) { |
$count = 0; |
} elseif ($count < ($this->limit_from + $limit_count)) { |
$count -= $this->limit_from; |
} else { |
$count = $limit_count; |
} |
} |
|
return $count; |
} |
|
// }}} |
1349,9 → 1465,9 |
* @category Database |
* @package DB |
* @author Stig Bakken <ssb@php.net> |
* @copyright 1997-2005 The PHP Group |
* @copyright 1997-2007 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.7.6 |
* @version Release: 1.9.2 |
* @link http://pear.php.net/package/DB |
* @see DB_common::setFetchMode() |
*/ |
1366,7 → 1482,7 |
* |
* @return void |
*/ |
function DB_row(&$arr) |
function __construct(&$arr) |
{ |
foreach ($arr as $key => $value) { |
$this->$key = &$arr[$key]; |