| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> | |
| | | // +----------------------------------------------------------------------+ |
| | | // |
| | | // $Id: MDB2.php,v 1.318 2008/03/08 14:18:38 quipo Exp $ |
| | | // $Id: MDB2.php 295587 2010-02-28 17:16:38Z quipo $ |
| | | // |
| | | |
| | | /** |
| | |
| | | define('MDB2_ERROR_LOADMODULE', -34); |
| | | define('MDB2_ERROR_INSUFFICIENT_DATA', -35); |
| | | define('MDB2_ERROR_NO_PERMISSION', -36); |
| | | define('MDB2_ERROR_DISCONNECT_FAILED', -37); |
| | | |
| | | // }}} |
| | | // {{{ Verbose constants |
| | |
| | | */ |
| | | class MDB2 |
| | | { |
| | | // {{{ function setOptions(&$db, $options) |
| | | // {{{ function setOptions($db, $options) |
| | | |
| | | /** |
| | | * set option array in an exiting database object |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function setOptions(&$db, $options) |
| | | static function setOptions($db, $options) |
| | | { |
| | | if (is_array($options)) { |
| | | foreach ($options as $option => $value) { |
| | |
| | | * @static |
| | | * @access public |
| | | */ |
| | | function classExists($classname) |
| | | static function classExists($classname) |
| | | { |
| | | if (version_compare(phpversion(), "5.0", ">=")) { |
| | | return class_exists($classname, false); |
| | | } |
| | | return class_exists($classname); |
| | | return class_exists($classname, false); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function loadClass($class_name, $debug) |
| | | static function loadClass($class_name, $debug) |
| | | { |
| | | if (!MDB2::classExists($class_name)) { |
| | | $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php'; |
| | |
| | | } else { |
| | | $msg = "unable to load class '$class_name' from file '$file_name'"; |
| | | } |
| | | $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg); |
| | | $err = MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg); |
| | | return $err; |
| | | } |
| | | if (!MDB2::classExists($class_name)) { |
| | | $msg = "unable to load class '$class_name' from file '$file_name'"; |
| | | $err = MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg); |
| | | return $err; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function &factory($dsn, $options = false) |
| | | // {{{ function factory($dsn, $options = false) |
| | | |
| | | /** |
| | | * Create a new MDB2 object for the specified database type |
| | | * |
| | | * IMPORTANT: In order for MDB2 to work properly it is necessary that |
| | | * you make sure that you work with a reference of the original |
| | | * object instead of a copy (this is a PHP4 quirk). |
| | | * |
| | | * For example: |
| | | * $db =& MDB2::factory($dsn); |
| | | * ^^ |
| | | * And not: |
| | | * $db = MDB2::factory($dsn); |
| | | * |
| | | * @param mixed 'data source name', see the MDB2::parseDSN |
| | | * method for a description of the dsn format. |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function &factory($dsn, $options = false) |
| | | static function factory($dsn, $options = false) |
| | | { |
| | | $dsninfo = MDB2::parseDSN($dsn); |
| | | if (empty($dsninfo['phptype'])) { |
| | | $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, |
| | | $err = MDB2::raiseError(MDB2_ERROR_NOT_FOUND, |
| | | null, null, 'no RDBMS driver specified'); |
| | | return $err; |
| | | } |
| | |
| | | return $err; |
| | | } |
| | | |
| | | $db =& new $class_name(); |
| | | $db = new $class_name(); |
| | | $db->setDSN($dsninfo); |
| | | $err = MDB2::setOptions($db, $options); |
| | | if (PEAR::isError($err)) { |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function &connect($dsn, $options = false) |
| | | // {{{ function connect($dsn, $options = false) |
| | | |
| | | /** |
| | | * Create a new MDB2 connection object and connect to the specified |
| | | * Create a new MDB2_Driver_* connection object and connect to the specified |
| | | * database |
| | | * |
| | | * IMPORTANT: In order for MDB2 to work properly it is necessary that |
| | | * you make sure that you work with a reference of the original |
| | | * object instead of a copy (this is a PHP4 quirk). |
| | | * @param mixed $dsn 'data source name', see the MDB2::parseDSN |
| | | * method for a description of the dsn format. |
| | | * Can also be specified as an array of the |
| | | * format returned by MDB2::parseDSN. |
| | | * @param array $options An associative array of option names and |
| | | * their values. |
| | | * |
| | | * For example: |
| | | * $db =& MDB2::connect($dsn); |
| | | * ^^ |
| | | * And not: |
| | | * $db = MDB2::connect($dsn); |
| | | * ^^ |
| | | * |
| | | * @param mixed 'data source name', see the MDB2::parseDSN |
| | | * method for a description of the dsn format. |
| | | * Can also be specified as an array of the |
| | | * format returned by MDB2::parseDSN. |
| | | * @param array An associative array of option names and |
| | | * their values. |
| | | * |
| | | * @return mixed a newly created MDB2 connection object, or a MDB2 |
| | | * error object on error |
| | | * @return mixed a newly created MDB2 connection object, or a MDB2 |
| | | * error object on error |
| | | * |
| | | * @access public |
| | | * @see MDB2::parseDSN |
| | | */ |
| | | function &connect($dsn, $options = false) |
| | | static function connect($dsn, $options = false) |
| | | { |
| | | $db =& MDB2::factory($dsn, $options); |
| | | $db = MDB2::factory($dsn, $options); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function &singleton($dsn = null, $options = false) |
| | | // {{{ function singleton($dsn = null, $options = false) |
| | | |
| | | /** |
| | | * Returns a MDB2 connection with the requested DSN. |
| | | * A new MDB2 connection object is only created if no object with the |
| | | * requested DSN exists yet. |
| | | * |
| | | * IMPORTANT: In order for MDB2 to work properly it is necessary that |
| | | * you make sure that you work with a reference of the original |
| | | * object instead of a copy (this is a PHP4 quirk). |
| | | * |
| | | * For example: |
| | | * $db =& MDB2::singleton($dsn); |
| | | * ^^ |
| | | * And not: |
| | | * $db = MDB2::singleton($dsn); |
| | | * ^^ |
| | | * |
| | | * @param mixed 'data source name', see the MDB2::parseDSN |
| | | * method for a description of the dsn format. |
| | |
| | | * @access public |
| | | * @see MDB2::parseDSN |
| | | */ |
| | | function &singleton($dsn = null, $options = false) |
| | | static function singleton($dsn = null, $options = false) |
| | | { |
| | | if ($dsn) { |
| | | $dsninfo = MDB2::parseDSN($dsn); |
| | |
| | | } |
| | | } |
| | | } elseif (is_array($GLOBALS['_MDB2_databases']) && reset($GLOBALS['_MDB2_databases'])) { |
| | | $db =& $GLOBALS['_MDB2_databases'][key($GLOBALS['_MDB2_databases'])]; |
| | | return $db; |
| | | return $GLOBALS['_MDB2_databases'][key($GLOBALS['_MDB2_databases'])]; |
| | | } |
| | | $db =& MDB2::factory($dsn, $options); |
| | | $db = MDB2::factory($dsn, $options); |
| | | return $db; |
| | | } |
| | | |
| | |
| | | * @param array $arr2 |
| | | * @return boolean |
| | | */ |
| | | function areEquals($arr1, $arr2) |
| | | static function areEquals($arr1, $arr2) |
| | | { |
| | | if (count($arr1) != count($arr2)) { |
| | | return false; |
| | |
| | | /** |
| | | * load a file (like 'Date') |
| | | * |
| | | * @param string name of the file in the MDB2 directory (without '.php') |
| | | * @param string $file name of the file in the MDB2 directory (without '.php') |
| | | * |
| | | * @return string name of the file that was included |
| | | * @return string name of the file that was included |
| | | * |
| | | * @access public |
| | | */ |
| | | function loadFile($file) |
| | | static function loadFile($file) |
| | | { |
| | | $file_name = 'MDB2'.DIRECTORY_SEPARATOR.$file.'.php'; |
| | | if (!MDB2::fileExists($file_name)) { |
| | |
| | | */ |
| | | function apiVersion() |
| | | { |
| | | return '2.5.0b1'; |
| | | return '@package_version@'; |
| | | } |
| | | |
| | | // }}} |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function isError($data, $code = null) |
| | | static function isError($data, $code = null) |
| | | { |
| | | if (is_a($data, 'MDB2_Error')) { |
| | | if (is_null($code)) { |
| | | if ($data instanceof MDB2_Error) { |
| | | if (null === $code) { |
| | | return true; |
| | | } elseif (is_string($code)) { |
| | | return $data->getMessage() === $code; |
| | | } else { |
| | | $code = (array)$code; |
| | | return in_array($data->getCode(), $code); |
| | | } |
| | | if (is_string($code)) { |
| | | return $data->getMessage() === $code; |
| | | } |
| | | return in_array($data->getCode(), (array)$code); |
| | | } |
| | | return false; |
| | | } |
| | |
| | | * @param mixed value to test |
| | | * |
| | | * @return bool whether $value is a MDB2 connection |
| | | * |
| | | * @access public |
| | | */ |
| | | function isConnection($value) |
| | | { |
| | | return is_a($value, 'MDB2_Driver_Common'); |
| | | return ($value instanceof MDB2_Driver_Common); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | /** |
| | | * Tell whether a value is a MDB2 result |
| | | * |
| | | * @param mixed value to test |
| | | * @param mixed $value value to test |
| | | * |
| | | * @return bool whether $value is a MDB2 result |
| | | * @return bool whether $value is a MDB2 result |
| | | * |
| | | * @access public |
| | | * @access public |
| | | */ |
| | | function isResult($value) |
| | | { |
| | | return is_a($value, 'MDB2_Result'); |
| | | return ($value instanceof MDB2_Result); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | /** |
| | | * Tell whether a value is a MDB2 result implementing the common interface |
| | | * |
| | | * @param mixed value to test |
| | | * @param mixed $value value to test |
| | | * |
| | | * @return bool whether $value is a MDB2 result implementing the common interface |
| | | * @return bool whether $value is a MDB2 result implementing the common interface |
| | | * |
| | | * @access public |
| | | */ |
| | | function isResultCommon($value) |
| | | static function isResultCommon($value) |
| | | { |
| | | return is_a($value, 'MDB2_Result_Common'); |
| | | return ($value instanceof MDB2_Result_Common); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | */ |
| | | function isStatement($value) |
| | | { |
| | | return is_a($value, 'MDB2_Statement_Common'); |
| | | return ($value instanceof MDB2_Statement_Common); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | MDB2_ERROR_TRUNCATED => 'truncated', |
| | | MDB2_ERROR_DEADLOCK => 'deadlock detected', |
| | | MDB2_ERROR_NO_PERMISSION => 'no permission', |
| | | MDB2_ERROR_DISCONNECT_FAILED => 'disconnect failed', |
| | | ); |
| | | } |
| | | |
| | | if (is_null($value)) { |
| | | if (null === $value) { |
| | | return $errorMessages; |
| | | } |
| | | |
| | |
| | | * @access public |
| | | * @author Tomas V.V.Cox <cox@idecnet.com> |
| | | */ |
| | | function parseDSN($dsn) |
| | | static function parseDSN($dsn) |
| | | { |
| | | $parsed = array(); |
| | | $parsed = $GLOBALS['_MDB2_dsninfo_default']; |
| | | |
| | | if (is_array($dsn)) { |
| | | $dsn = array_merge($parsed, $dsn); |
| | |
| | | $dsn = null; |
| | | } |
| | | |
| | | |
| | | // Get phptype and dbsyntax |
| | | // $str => phptype(dbsyntax) |
| | | if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) { |
| | |
| | | } |
| | | |
| | | if (!count($dsn)) { |
| | | return array_merge($GLOBALS['_MDB2_dsninfo_default'], $parsed); |
| | | return $parsed; |
| | | } |
| | | |
| | | // Get (if found): username and password |
| | |
| | | //"username/password@[//]host[:port][/service_name]" |
| | | //e.g. "scott/tiger@//mymachine:1521/oracle" |
| | | $proto_opts = $dsn; |
| | | $dsn = substr($proto_opts, strrpos($proto_opts, '/') + 1); |
| | | $pos = strrpos($proto_opts, '/'); |
| | | $dsn = substr($proto_opts, $pos + 1); |
| | | $proto_opts = substr($proto_opts, 0, $pos); |
| | | } elseif (strpos($dsn, '/') !== false) { |
| | | list($proto_opts, $dsn) = explode('/', $dsn, 2); |
| | | } else { |
| | |
| | | if ($dsn) { |
| | | // /database |
| | | if (($pos = strpos($dsn, '?')) === false) { |
| | | $parsed['database'] = $dsn; |
| | | $parsed['database'] = rawurldecode($dsn); |
| | | // /database?param1=value1¶m2=value2 |
| | | } else { |
| | | $parsed['database'] = substr($dsn, 0, $pos); |
| | | $parsed['database'] = rawurldecode(substr($dsn, 0, $pos)); |
| | | $dsn = substr($dsn, $pos + 1); |
| | | if (strpos($dsn, '&') !== false) { |
| | | $opts = explode('&', $dsn); |
| | |
| | | } |
| | | foreach ($opts as $opt) { |
| | | list($key, $value) = explode('=', $opt); |
| | | if (!isset($parsed[$key])) { |
| | | if (!array_key_exists($key, $parsed) || false === $parsed[$key]) { |
| | | // don't allow params overwrite |
| | | $parsed[$key] = rawurldecode($value); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | return array_merge($GLOBALS['_MDB2_dsninfo_default'], $parsed); |
| | | return $parsed; |
| | | } |
| | | |
| | | // }}} |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function fileExists($file) |
| | | static function fileExists($file) |
| | | { |
| | | // safe_mode does notwork with is_readable() |
| | | if (!@ini_get('safe_mode')) { |
| | |
| | | * @param int what error level to use for $mode & PEAR_ERROR_TRIGGER |
| | | * @param mixed additional debug info, such as the last query |
| | | */ |
| | | function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, |
| | | function __construct($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, |
| | | $level = E_USER_NOTICE, $debuginfo = null, $dummy = null) |
| | | { |
| | | if (is_null($code)) { |
| | | if (null === $code) { |
| | | $code = MDB2_ERROR; |
| | | } |
| | | $this->PEAR_Error('MDB2 Error: '.MDB2::errorMessage($code), $code, |
| | |
| | | * <li>$options['emulate_prepared'] -> boolean: force prepared statements to be emulated</li> |
| | | * <li>$options['datatype_map'] -> array: map user defined datatypes to other primitive datatypes</li> |
| | | * <li>$options['datatype_map_callback'] -> array: callback function/method that should be called</li> |
| | | * <li>$options['bindname_format'] -> string: regular expression pattern for named parameters |
| | | * <li>$options['bindname_format'] -> string: regular expression pattern for named parameters</li> |
| | | * <li>$options['multi_query'] -> boolean: determines if queries returning multiple result sets should be executed</li> |
| | | * <li>$options['max_identifiers_length'] -> integer: max identifier length</li> |
| | | * <li>$options['default_fk_action_onupdate'] -> string: default FOREIGN KEY ON UPDATE action ['RESTRICT'|'NO ACTION'|'SET DEFAULT'|'SET NULL'|'CASCADE']</li> |
| | | * <li>$options['default_fk_action_ondelete'] -> string: default FOREIGN KEY ON DELETE action ['RESTRICT'|'NO ACTION'|'SET DEFAULT'|'SET NULL'|'CASCADE']</li> |
| | | * </ul> |
| | | * |
| | | * @var array |
| | |
| | | 'lob_allow_url_include' => false, |
| | | 'bindname_format' => '(?:\d+)|(?:[a-zA-Z][a-zA-Z0-9_]*)', |
| | | 'max_identifiers_length' => 30, |
| | | 'default_fk_action_onupdate' => 'RESTRICT', |
| | | 'default_fk_action_ondelete' => 'RESTRICT', |
| | | ); |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function MDB2_Driver_Common() |
| | | |
| | | /** |
| | | * PHP 4 Constructor |
| | | */ |
| | | function MDB2_Driver_Common() |
| | | { |
| | | $this->destructor_registered = false; |
| | | $this->__construct(); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ destructor: function __destruct() |
| | | |
| | | /** |
| | |
| | | * callbacks etc. Basically a wrapper for PEAR::raiseError |
| | | * without the message string. |
| | | * |
| | | * @param mixed integer error code, or a PEAR error object (all other |
| | | * parameters are ignored if this parameter is an object |
| | | * @param int error mode, see PEAR_Error docs |
| | | * @param mixed If error mode is PEAR_ERROR_TRIGGER, this is the |
| | | * error level (E_USER_NOTICE etc). If error mode is |
| | | * PEAR_ERROR_CALLBACK, this is the callback function, |
| | | * either as a function name, or as an array of an |
| | | * object and method name. For other error modes this |
| | | * parameter is ignored. |
| | | * @param string Extra debug information. Defaults to the last |
| | | * query and native error code. |
| | | * @param string name of the method that triggered the error |
| | | * @param mixed $code integer error code, or a PEAR error object (all |
| | | * other parameters are ignored if this parameter is |
| | | * an object |
| | | * @param int $mode error mode, see PEAR_Error docs |
| | | * @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the |
| | | * error level (E_USER_NOTICE etc). If error mode is |
| | | * PEAR_ERROR_CALLBACK, this is the callback function, |
| | | * either as a function name, or as an array of an |
| | | * object and method name. For other error modes this |
| | | * parameter is ignored. |
| | | * @param string $userinfo Extra debug information. Defaults to the last |
| | | * query and native error code. |
| | | * @param string $method name of the method that triggered the error |
| | | * @param string $dummy1 not used |
| | | * @param bool $dummy2 not used |
| | | * |
| | | * @return PEAR_Error instance of a PEAR Error object |
| | | * |
| | | * @access public |
| | | * @see PEAR_Error |
| | | * @return PEAR_Error instance of a PEAR Error object |
| | | * @access public |
| | | * @see PEAR_Error |
| | | */ |
| | | function &raiseError($code = null, $mode = null, $options = null, $userinfo = null, $method = null) |
| | | { |
| | | function &raiseError($code = null, |
| | | $mode = null, |
| | | $options = null, |
| | | $userinfo = null, |
| | | $method = null, |
| | | $dummy1 = null, |
| | | $dummy2 = false |
| | | ) { |
| | | $userinfo = "[Error message: $userinfo]\n"; |
| | | // The error is yet a MDB2 error object |
| | | if (PEAR::isError($code)) { |
| | | // because we use the static PEAR::raiseError, our global |
| | | // handler should be used if it is set |
| | | if (is_null($mode) && !empty($this->_default_error_mode)) { |
| | | if ((null === $mode) && !empty($this->_default_error_mode)) { |
| | | $mode = $this->_default_error_mode; |
| | | $options = $this->_default_error_options; |
| | | } |
| | | if (is_null($userinfo)) { |
| | | if (null === $userinfo) { |
| | | $userinfo = $code->getUserinfo(); |
| | | } |
| | | $code = $code->getCode(); |
| | |
| | | } |
| | | $native_errno = $native_msg = null; |
| | | list($code, $native_errno, $native_msg) = $this->errorInfo($code); |
| | | if (!is_null($native_errno) && $native_errno !== '') { |
| | | if ((null !== $native_errno) && $native_errno !== '') { |
| | | $userinfo.= "[Native code: $native_errno]\n"; |
| | | } |
| | | if (!is_null($native_msg) && $native_msg !== '') { |
| | | if ((null !== $native_msg) && $native_msg !== '') { |
| | | $userinfo.= "[Native message: ". strip_tags($native_msg) ."]\n"; |
| | | } |
| | | if (!is_null($method)) { |
| | | if (null !== $method) { |
| | | $userinfo = $method.': '.$userinfo; |
| | | } |
| | | } |
| | | |
| | | $err =& PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true); |
| | | $err = PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true); |
| | | if ($err->getMode() !== PEAR_ERROR_RETURN |
| | | && isset($this->nested_transaction_counter) && !$this->has_transaction_error) { |
| | | $this->has_transaction_error =& $err; |
| | | $this->has_transaction_error = $err; |
| | | } |
| | | return $err; |
| | | } |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function &loadModule($module, $property = null, $phptype_specific = null) |
| | | // {{{ function loadModule($module, $property = null, $phptype_specific = null) |
| | | |
| | | /** |
| | | * loads a module |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function &loadModule($module, $property = null, $phptype_specific = null) |
| | | function loadModule($module, $property = null, $phptype_specific = null) |
| | | { |
| | | if (!$property) { |
| | | $property = strtolower($module); |
| | |
| | | } |
| | | |
| | | if (!MDB2::classExists($class_name)) { |
| | | $err =& $this->raiseError(MDB2_ERROR_LOADMODULE, null, null, |
| | | $err = $this->raiseError(MDB2_ERROR_LOADMODULE, null, null, |
| | | "unable to load module '$module' into property '$property'", __FUNCTION__); |
| | | return $err; |
| | | } |
| | | $this->{$property} = new $class_name($this->db_index); |
| | | $this->modules[$module] =& $this->{$property}; |
| | | $this->modules[$module] = $this->{$property}; |
| | | if ($version) { |
| | | // this will be used in the connect method to determine if the module |
| | | // needs to be loaded with a different version if the server |
| | |
| | | $module = $this->options['modules'][$match[1]]; |
| | | $method = strtolower($match[2]).$match[3]; |
| | | if (!isset($this->modules[$module]) || !is_object($this->modules[$module])) { |
| | | $result =& $this->loadModule($module); |
| | | $result = $this->loadModule($module); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | |
| | | } |
| | | } |
| | | } |
| | | if (!is_null($module)) { |
| | | if (null !== $module) { |
| | | return call_user_func_array(array(&$this->modules[$module], $method), $params); |
| | | } |
| | | trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $method), E_USER_ERROR); |
| | |
| | | */ |
| | | function failNestedTransaction($error = null, $immediately = false) |
| | | { |
| | | if (is_null($error)) { |
| | | if (null !== $error) { |
| | | $error = $this->has_transaction_error ? $this->has_transaction_error : true; |
| | | } elseif (!$error) { |
| | | $error = true; |
| | |
| | | /** |
| | | * Log out and disconnect from the database. |
| | | * |
| | | * @param bool if the disconnect should be forced even if the |
| | | * connection is opened persistently |
| | | * @param boolean $force whether the disconnect should be forced even if the |
| | | * connection is opened persistently |
| | | * |
| | | * @return mixed true on success, false if not connected and error |
| | | * object on error |
| | | * @return mixed true on success, false if not connected and error object on error |
| | | * |
| | | * @access public |
| | | */ |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ _isNewLinkSet() |
| | | |
| | | /** |
| | | * Check if the 'new_link' option is set |
| | | * |
| | | * @return boolean |
| | | * |
| | | * @access protected |
| | | */ |
| | | function _isNewLinkSet() |
| | | { |
| | | return (isset($this->dsn['new_link']) |
| | | && ($this->dsn['new_link'] === true |
| | | || (is_string($this->dsn['new_link']) && preg_match('/^true$/i', $this->dsn['new_link'])) |
| | | || (is_numeric($this->dsn['new_link']) && 0 != (int)$this->dsn['new_link']) |
| | | ) |
| | | ); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function &standaloneQuery($query, $types = null, $is_manip = false) |
| | | |
| | | /** |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function &standaloneQuery($query, $types = null, $is_manip = false) |
| | | function standaloneQuery($query, $types = null, $is_manip = false) |
| | | { |
| | | $offset = $this->offset; |
| | | $limit = $this->limit; |
| | |
| | | return $connection; |
| | | } |
| | | |
| | | $result =& $this->_doQuery($query, $is_manip, $connection, false); |
| | | $result = $this->_doQuery($query, $is_manip, $connection, false); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | |
| | | $affected_rows = $this->_affectedRows($connection, $result); |
| | | return $affected_rows; |
| | | } |
| | | $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset); |
| | | $result = $this->_wrapResult($result, $types, true, false, $limit, $offset); |
| | | return $result; |
| | | } |
| | | |
| | |
| | | * |
| | | * @access protected |
| | | */ |
| | | function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) |
| | | function _doQuery($query, $is_manip = false, $connection = null, $database_name = null) |
| | | { |
| | | $this->last_query = $query; |
| | | $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')); |
| | |
| | | } |
| | | $query = $result; |
| | | } |
| | | $err =& $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
| | | $err = $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
| | | 'method not implemented', __FUNCTION__); |
| | | return $err; |
| | | } |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function &exec($query) |
| | | function exec($query) |
| | | { |
| | | $offset = $this->offset; |
| | | $limit = $this->limit; |
| | |
| | | return $connection; |
| | | } |
| | | |
| | | $result =& $this->_doQuery($query, true, $connection, $this->database_name); |
| | | $result = $this->_doQuery($query, true, $connection, $this->database_name); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function &query($query, $types = null, $result_class = true, $result_wrap_class = false) |
| | | function query($query, $types = null, $result_class = true, $result_wrap_class = false) |
| | | { |
| | | $offset = $this->offset; |
| | | $limit = $this->limit; |
| | |
| | | return $connection; |
| | | } |
| | | |
| | | $result =& $this->_doQuery($query, false, $connection, $this->database_name); |
| | | $result = $this->_doQuery($query, false, $connection, $this->database_name); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | |
| | | $result =& $this->_wrapResult($result, $types, $result_class, $result_wrap_class, $limit, $offset); |
| | | $result = $this->_wrapResult($result, $types, $result_class, $result_wrap_class, $limit, $offset); |
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function &_wrapResult($result, $types = array(), $result_class = true, $result_wrap_class = false, $limit = null, $offset = null) |
| | | // {{{ function _wrapResult($result_resource, $types = array(), $result_class = true, $result_wrap_class = false, $limit = null, $offset = null) |
| | | |
| | | /** |
| | | * wrap a result set into the correct class |
| | |
| | | * |
| | | * @access protected |
| | | */ |
| | | function &_wrapResult($result, $types = array(), $result_class = true, |
| | | function _wrapResult($result_resource, $types = array(), $result_class = true, |
| | | $result_wrap_class = false, $limit = null, $offset = null) |
| | | { |
| | | if ($types === true) { |
| | | if ($this->supports('result_introspection')) { |
| | | $this->loadModule('Reverse', null, true); |
| | | $tableInfo = $this->reverse->tableInfo($result); |
| | | $tableInfo = $this->reverse->tableInfo($result_resource); |
| | | if (PEAR::isError($tableInfo)) { |
| | | return $tableInfo; |
| | | } |
| | |
| | | if ($result_class) { |
| | | $class_name = sprintf($result_class, $this->phptype); |
| | | if (!MDB2::classExists($class_name)) { |
| | | $err =& $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | $err = $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | 'result class does not exist '.$class_name, __FUNCTION__); |
| | | return $err; |
| | | } |
| | | $result =& new $class_name($this, $result, $limit, $offset); |
| | | $result = new $class_name($this, $result_resource, $limit, $offset); |
| | | if (!MDB2::isResultCommon($result)) { |
| | | $err =& $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | $err = $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | 'result class is not extended from MDB2_Result_Common', __FUNCTION__); |
| | | return $err; |
| | | } |
| | |
| | | } |
| | | if ($result_wrap_class) { |
| | | if (!MDB2::classExists($result_wrap_class)) { |
| | | $err =& $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | $err = $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | 'result wrap class does not exist '.$result_wrap_class, __FUNCTION__); |
| | | return $err; |
| | | } |
| | | $result = new $result_wrap_class($result, $this->fetchmode); |
| | | $result = new $result_wrap_class($result_resource, $this->fetchmode); |
| | | } |
| | | return $result; |
| | | } |
| | |
| | | 'it was not specified a valid selected range row limit', __FUNCTION__); |
| | | } |
| | | $this->limit = $limit; |
| | | if (!is_null($offset)) { |
| | | if (null !== $offset) { |
| | | $offset = (int)$offset; |
| | | if ($offset < 0) { |
| | | return $this->raiseError(MDB2_ERROR_SYNTAX, null, null, |
| | |
| | | /** |
| | | * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT |
| | | * query, except that if there is already a row in the table with the same |
| | | * key field values, the REPLACE query just updates its values instead of |
| | | * inserting a new row. |
| | | * key field values, the old row is deleted before the new row is inserted. |
| | | * |
| | | * The REPLACE type of query does not make part of the SQL standards. Since |
| | | * practically only MySQL and SQLite implement it natively, this type of |
| | |
| | | |
| | | $condition = ' WHERE '.implode(' AND ', $condition); |
| | | $query = 'DELETE FROM ' . $this->quoteIdentifier($table, true) . $condition; |
| | | $result =& $this->_doQuery($query, true, $connection); |
| | | $result = $this->_doQuery($query, true, $connection); |
| | | if (!PEAR::isError($result)) { |
| | | $affected_rows = $this->_affectedRows($connection, $result); |
| | | $insert = ''; |
| | |
| | | } |
| | | $values = implode(', ', $values); |
| | | $query = 'INSERT INTO '. $this->quoteIdentifier($table, true) . "($insert) VALUES ($values)"; |
| | | $result =& $this->_doQuery($query, true, $connection); |
| | | $result = $this->_doQuery($query, true, $connection); |
| | | if (!PEAR::isError($result)) { |
| | | $affected_rows += $this->_affectedRows($connection, $result);; |
| | | } |
| | |
| | | * @access public |
| | | * @see bindParam, execute |
| | | */ |
| | | function &prepare($query, $types = null, $result_types = null, $lobs = array()) |
| | | function prepare($query, $types = null, $result_types = null, $lobs = array()) |
| | | { |
| | | $is_manip = ($result_types === MDB2_PREPARE_MANIP); |
| | | $offset = $this->offset; |
| | |
| | | $query = $result; |
| | | } |
| | | $placeholder_type_guess = $placeholder_type = null; |
| | | $question = '?'; |
| | | $colon = ':'; |
| | | $question = '?'; |
| | | $colon = ':'; |
| | | $positions = array(); |
| | | $position = 0; |
| | | |
| | | $position = 0; |
| | | while ($position < strlen($query)) { |
| | | $q_position = strpos($query, $question, $position); |
| | | $c_position = strpos($query, $colon, $position); |
| | |
| | | } else { |
| | | break; |
| | | } |
| | | if (is_null($placeholder_type)) { |
| | | if (null === $placeholder_type) { |
| | | $placeholder_type_guess = $query[$p_position]; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if ($query[$position] == $placeholder_type_guess) { |
| | | if (is_null($placeholder_type)) { |
| | | if (null === $placeholder_type) { |
| | | $placeholder_type = $query[$p_position]; |
| | | $question = $colon = $placeholder_type; |
| | | if (!empty($types) && is_array($types)) { |
| | |
| | | $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s'; |
| | | $parameter = preg_replace($regexp, '\\1', $query); |
| | | if ($parameter === '') { |
| | | $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null, |
| | | $err = $this->raiseError(MDB2_ERROR_SYNTAX, null, null, |
| | | 'named parameter name must match "bindname_format" option', __FUNCTION__); |
| | | return $err; |
| | | } |
| | |
| | | */ |
| | | function _skipDelimitedStrings($query, $position, $p_position) |
| | | { |
| | | $ignores[] = $this->string_quoting; |
| | | $ignores[] = $this->identifier_quoting;
|
| | | $ignores = array(); |
| | | $ignores[] = $this->string_quoting; |
| | | $ignores[] = $this->identifier_quoting; |
| | | $ignores = array_merge($ignores, $this->sql_comments); |
| | | |
| | | foreach ($ignores as $ignore) { |
| | |
| | | if ($ignore['end'] === "\n") { |
| | | $end_quote = strlen($query) - 1; |
| | | } else { |
| | | $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null, |
| | | $err = $this->raiseError(MDB2_ERROR_SYNTAX, null, null, |
| | | 'query with an unterminated text string specified', __FUNCTION__); |
| | | return $err; |
| | | } |
| | | } |
| | | } while ($ignore['escape'] |
| | | && $end_quote-1 != $start_quote |
| | | && $query[($end_quote - 1)] == $ignore['escape'] |
| | | && ($ignore['escape_pattern'] !== $ignore['escape'] |
| | | || $query[($end_quote - 2)] != $ignore['escape'])); |
| | | && $end_quote-1 != $start_quote |
| | | && $query[($end_quote - 1)] == $ignore['escape'] |
| | | && ( $ignore['escape_pattern'] !== $ignore['escape'] |
| | | || $query[($end_quote - 2)] != $ignore['escape']) |
| | | ); |
| | | |
| | | $position = $end_quote + 1; |
| | | return $position; |
| | | } |
| | |
| | | function getIndexName($idx) |
| | | { |
| | | return sprintf($this->options['idxname_format'], |
| | | preg_replace('/[^a-z0-9_\$]/i', '_', $idx)); |
| | | preg_replace('/[^a-z0-9_\-\$.]/i', '_', $idx)); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | * the first row of the result set and then frees |
| | | * the result set. |
| | | * |
| | | * @param string the SELECT query statement to be executed. |
| | | * @param string optional argument that specifies the expected |
| | | * datatype of the result set field, so that an eventual conversion |
| | | * may be performed. The default datatype is text, meaning that no |
| | | * conversion is performed |
| | | * @param int the column number to fetch |
| | | * @param string $query the SELECT query statement to be executed. |
| | | * @param string $type optional argument that specifies the expected |
| | | * datatype of the result set field, so that an eventual |
| | | * conversion may be performed. The default datatype is |
| | | * text, meaning that no conversion is performed |
| | | * @param mixed $colnum the column number (or name) to fetch |
| | | * |
| | | * @return mixed MDB2_OK or field value on success, a MDB2 error on failure |
| | | * |
| | |
| | | * Execute the specified query, fetch the value from the first column of |
| | | * each row of the result set into an array and then frees the result set. |
| | | * |
| | | * @param string the SELECT query statement to be executed. |
| | | * @param string optional argument that specifies the expected |
| | | * datatype of the result set field, so that an eventual conversion |
| | | * may be performed. The default datatype is text, meaning that no |
| | | * conversion is performed |
| | | * @param int the row number to fetch |
| | | * @param string $query the SELECT query statement to be executed. |
| | | * @param string $type optional argument that specifies the expected |
| | | * datatype of the result set field, so that an eventual |
| | | * conversion may be performed. The default datatype is text, |
| | | * meaning that no conversion is performed |
| | | * @param mixed $colnum the column number (or name) to fetch |
| | | * |
| | | * @return mixed MDB2_OK or data array on success, a MDB2 error on failure |
| | | * |
| | | * @access public |
| | | */ |
| | | function queryCol($query, $type = null, $colnum = 0) |
| | |
| | | var $column_names; |
| | | |
| | | // }}} |
| | | // {{{ constructor: function __construct(&$db, &$result, $limit = 0, $offset = 0) |
| | | // {{{ constructor: function __construct($db, &$result, $limit = 0, $offset = 0) |
| | | |
| | | /** |
| | | * Constructor |
| | | */ |
| | | function __construct(&$db, &$result, $limit = 0, $offset = 0) |
| | | function __construct($db, &$result, $limit = 0, $offset = 0) |
| | | { |
| | | $this->db =& $db; |
| | | $this->result =& $result; |
| | | $this->db = $db; |
| | | $this->result = $result; |
| | | $this->offset = $offset; |
| | | $this->limit = max(0, $limit - 1); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function MDB2_Result_Common(&$db, &$result, $limit = 0, $offset = 0) |
| | | |
| | | /** |
| | | * PHP 4 Constructor |
| | | */ |
| | | function MDB2_Result_Common(&$db, &$result, $limit = 0, $offset = 0) |
| | | { |
| | | $this->__construct($db, $result, $limit, $offset); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) |
| | | function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) |
| | | { |
| | | $err =& $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
| | | $err = $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
| | | 'method not implemented', __FUNCTION__); |
| | | return $err; |
| | | } |
| | |
| | | /** |
| | | * fetch single column from the next row from a result set |
| | | * |
| | | * @param int the column number to fetch |
| | | * @param int number of the row where the data can be found |
| | | * @param int|string the column number (or name) to fetch |
| | | * @param int number of the row where the data can be found |
| | | * |
| | | * @return string data on success, a MDB2 error on failure |
| | | * |
| | | * @return string data on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function fetchOne($colnum = 0, $rownum = null) |
| | |
| | | /** |
| | | * Fetch and return a column from the current row pointer position |
| | | * |
| | | * @param int the column number to fetch |
| | | * @param int|string the column number (or name) to fetch |
| | | * |
| | | * @return mixed data array on success, a MDB2 error on failure |
| | | * |
| | | * @return mixed data array on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function fetchCol($colnum = 0) |
| | |
| | | } |
| | | |
| | | $shift_array = $rekey ? false : null; |
| | | if (!is_null($shift_array)) { |
| | | if (null !== $shift_array) { |
| | | if (is_object($row)) { |
| | | $colnum = count(get_object_vars($row)); |
| | | } else { |
| | |
| | | $column = $column_names[$column]; |
| | | } |
| | | $this->values[$column] =& $value; |
| | | if (!is_null($type)) { |
| | | if (null !== $type) { |
| | | $this->types[$column] = $type; |
| | | } |
| | | return MDB2_OK; |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function MDB2_Row(&$row) |
| | | |
| | | /** |
| | | * PHP 4 Constructor |
| | | * |
| | | * @param resource row data as array |
| | | */ |
| | | function MDB2_Row(&$row) |
| | | { |
| | | $this->__construct($row); |
| | | } |
| | | |
| | | // }}} |
| | | } |
| | | |
| | | // }}} |
| | |
| | | var $is_manip; |
| | | |
| | | // }}} |
| | | // {{{ constructor: function __construct(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) |
| | | // {{{ constructor: function __construct($db, $statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) |
| | | |
| | | /** |
| | | * Constructor |
| | | */ |
| | | function __construct(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) |
| | | function __construct($db, $statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) |
| | | { |
| | | $this->db =& $db; |
| | | $this->statement =& $statement; |
| | | $this->db = $db; |
| | | $this->statement = $statement; |
| | | $this->positions = $positions; |
| | | $this->query = $query; |
| | | $this->types = (array)$types; |
| | |
| | | $this->limit = $limit; |
| | | $this->is_manip = $is_manip; |
| | | $this->offset = $offset; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function MDB2_Statement_Common(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) |
| | | |
| | | /** |
| | | * PHP 4 Constructor |
| | | */ |
| | | function MDB2_Statement_Common(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) |
| | | { |
| | | $this->__construct($db, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); |
| | | } |
| | | $this->values[$parameter] = $value; |
| | | if (!is_null($type)) { |
| | | if (null !== $type) { |
| | | $this->types[$parameter] = $type; |
| | | } |
| | | return MDB2_OK; |
| | |
| | | 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); |
| | | } |
| | | $this->values[$parameter] =& $value; |
| | | if (!is_null($type)) { |
| | | if (null !== $type) { |
| | | $this->types[$parameter] = $type; |
| | | } |
| | | return MDB2_OK; |
| | |
| | | /** |
| | | * Execute a prepared query statement. |
| | | * |
| | | * @param array specifies all necessary information |
| | | * for bindParam() the array elements must use keys corresponding to |
| | | * the number of the position of the parameter. |
| | | * @param mixed specifies which result class to use |
| | | * @param mixed specifies which class to wrap results in |
| | | * @param array specifies all necessary information |
| | | * for bindParam() the array elements must use keys corresponding |
| | | * to the number of the position of the parameter. |
| | | * @param mixed specifies which result class to use |
| | | * @param mixed specifies which class to wrap results in |
| | | * |
| | | * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure |
| | | * |
| | | * @access public |
| | | * @return mixed MDB2_Result or integer (affected rows) on success, |
| | | * a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function &execute($values = null, $result_class = true, $result_wrap_class = false) |
| | | function execute($values = null, $result_class = true, $result_wrap_class = false) |
| | | { |
| | | if (is_null($this->positions)) { |
| | | if (null === $this->positions) { |
| | | return $this->db->raiseError(MDB2_ERROR, null, null, |
| | | 'Prepared statement has already been freed', __FUNCTION__); |
| | | } |
| | |
| | | 'Binding Values failed with message: ' . $err->getMessage(), __FUNCTION__); |
| | | } |
| | | } |
| | | $result =& $this->_execute($result_class, $result_wrap_class); |
| | | $result = $this->_execute($result_class, $result_wrap_class); |
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function &_execute($result_class = true, $result_wrap_class = false) |
| | | // {{{ function _execute($result_class = true, $result_wrap_class = false) |
| | | |
| | | /** |
| | | * Execute a prepared query statement helper method. |
| | |
| | | * @param mixed specifies which result class to use |
| | | * @param mixed specifies which class to wrap results in |
| | | * |
| | | * @return mixed MDB2_Result or integer on success, a MDB2 error on failure |
| | | * |
| | | * @return mixed MDB2_Result or integer (affected rows) on success, |
| | | * a MDB2 error on failure |
| | | * @access private |
| | | */ |
| | | function &_execute($result_class = true, $result_wrap_class = false) |
| | | function _execute($result_class = true, $result_wrap_class = false) |
| | | { |
| | | $this->last_query = $this->query; |
| | | $query = ''; |
| | |
| | | if ($this->is_manip) { |
| | | $result = $this->db->exec($query); |
| | | } else { |
| | | $result =& $this->db->query($query, $this->result_types, $result_class, $result_wrap_class); |
| | | $result = $this->db->query($query, $this->result_types, $result_class, $result_wrap_class); |
| | | } |
| | | return $result; |
| | | } |
| | |
| | | */ |
| | | function free() |
| | | { |
| | | if (is_null($this->positions)) { |
| | | if (null === $this->positions) { |
| | | return $this->db->raiseError(MDB2_ERROR, null, null, |
| | | 'Prepared statement has already been freed', __FUNCTION__); |
| | | } |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function MDB2_Module_Common($db_index) |
| | | |
| | | /** |
| | | * PHP 4 Constructor |
| | | */ |
| | | function MDB2_Module_Common($db_index) |
| | | { |
| | | $this->__construct($db_index); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function &getDBInstance() |
| | | // {{{ function getDBInstance() |
| | | |
| | | /** |
| | | * Get the instance of MDB2 associated with the module instance |
| | |
| | | * |
| | | * @access public |
| | | */ |
| | | function &getDBInstance() |
| | | function getDBInstance() |
| | | { |
| | | if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { |
| | | $result =& $GLOBALS['_MDB2_databases'][$this->db_index]; |
| | | $result = $GLOBALS['_MDB2_databases'][$this->db_index]; |
| | | } else { |
| | | $result =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | $result = MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | 'could not find MDB2 instance'); |
| | | } |
| | | return $result; |