/tags/1.3b/includes/pear/MDB2.php
PHP | 4271 lines | 1844 code | 373 blank | 2054 comment | 300 complexity | 0d4093f6d7db5ec64434116b700e9a82 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, Apache-2.0
Large files files are truncated, but you can click here to view the full file
- <?php
- // vim: set et ts=4 sw=4 fdm=marker:
- // +----------------------------------------------------------------------+
- // | PHP versions 4 and 5 |
- // +----------------------------------------------------------------------+
- // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
- // | Stig. S. Bakken, Lukas Smith |
- // | All rights reserved. |
- // +----------------------------------------------------------------------+
- // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
- // | API as well as database abstraction for PHP applications. |
- // | This LICENSE is in the BSD license style. |
- // | |
- // | Redistribution and use in source and binary forms, with or without |
- // | modification, are permitted provided that the following conditions |
- // | are met: |
- // | |
- // | Redistributions of source code must retain the above copyright |
- // | notice, this list of conditions and the following disclaimer. |
- // | |
- // | Redistributions in binary form must reproduce the above copyright |
- // | notice, this list of conditions and the following disclaimer in the |
- // | documentation and/or other materials provided with the distribution. |
- // | |
- // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
- // | Lukas Smith nor the names of his contributors may be used to endorse |
- // | or promote products derived from this software without specific prior|
- // | written permission. |
- // | |
- // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
- // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
- // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
- // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
- // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
- // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
- // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
- // | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
- // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
- // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
- // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
- // | POSSIBILITY OF SUCH DAMAGE. |
- // +----------------------------------------------------------------------+
- // | Author: Lukas Smith <smith@pooteeweet.org> |
- // +----------------------------------------------------------------------+
- //
- // $Id: MDB2.php,v 1.292 2007/04/25 09:31:01 quipo Exp $
- //
- /**
- * @package MDB2
- * @category Database
- * @author Lukas Smith <smith@pooteeweet.org>
- */
- require_once 'PEAR.php';
- // {{{ Error constants
- /**
- * The method mapErrorCode in each MDB2_dbtype implementation maps
- * native error codes to one of these.
- *
- * If you add an error code here, make sure you also add a textual
- * version of it in MDB2::errorMessage().
- */
- define('MDB2_OK', true);
- define('MDB2_ERROR', -1);
- define('MDB2_ERROR_SYNTAX', -2);
- define('MDB2_ERROR_CONSTRAINT', -3);
- define('MDB2_ERROR_NOT_FOUND', -4);
- define('MDB2_ERROR_ALREADY_EXISTS', -5);
- define('MDB2_ERROR_UNSUPPORTED', -6);
- define('MDB2_ERROR_MISMATCH', -7);
- define('MDB2_ERROR_INVALID', -8);
- define('MDB2_ERROR_NOT_CAPABLE', -9);
- define('MDB2_ERROR_TRUNCATED', -10);
- define('MDB2_ERROR_INVALID_NUMBER', -11);
- define('MDB2_ERROR_INVALID_DATE', -12);
- define('MDB2_ERROR_DIVZERO', -13);
- define('MDB2_ERROR_NODBSELECTED', -14);
- define('MDB2_ERROR_CANNOT_CREATE', -15);
- define('MDB2_ERROR_CANNOT_DELETE', -16);
- define('MDB2_ERROR_CANNOT_DROP', -17);
- define('MDB2_ERROR_NOSUCHTABLE', -18);
- define('MDB2_ERROR_NOSUCHFIELD', -19);
- define('MDB2_ERROR_NEED_MORE_DATA', -20);
- define('MDB2_ERROR_NOT_LOCKED', -21);
- define('MDB2_ERROR_VALUE_COUNT_ON_ROW', -22);
- define('MDB2_ERROR_INVALID_DSN', -23);
- define('MDB2_ERROR_CONNECT_FAILED', -24);
- define('MDB2_ERROR_EXTENSION_NOT_FOUND',-25);
- define('MDB2_ERROR_NOSUCHDB', -26);
- define('MDB2_ERROR_ACCESS_VIOLATION', -27);
- define('MDB2_ERROR_CANNOT_REPLACE', -28);
- define('MDB2_ERROR_CONSTRAINT_NOT_NULL',-29);
- define('MDB2_ERROR_DEADLOCK', -30);
- define('MDB2_ERROR_CANNOT_ALTER', -31);
- define('MDB2_ERROR_MANAGER', -32);
- define('MDB2_ERROR_MANAGER_PARSE', -33);
- define('MDB2_ERROR_LOADMODULE', -34);
- define('MDB2_ERROR_INSUFFICIENT_DATA', -35);
- // }}}
- // {{{ Verbose constants
- /**
- * These are just helper constants to more verbosely express parameters to prepare()
- */
- define('MDB2_PREPARE_MANIP', false);
- define('MDB2_PREPARE_RESULT', null);
- // }}}
- // {{{ Fetchmode constants
- /**
- * This is a special constant that tells MDB2 the user hasn't specified
- * any particular get mode, so the default should be used.
- */
- define('MDB2_FETCHMODE_DEFAULT', 0);
- /**
- * Column data indexed by numbers, ordered from 0 and up
- */
- define('MDB2_FETCHMODE_ORDERED', 1);
- /**
- * Column data indexed by column names
- */
- define('MDB2_FETCHMODE_ASSOC', 2);
- /**
- * Column data as object properties
- */
- define('MDB2_FETCHMODE_OBJECT', 3);
- /**
- * For multi-dimensional results: normally the first level of arrays
- * is the row number, and the second level indexed by column number or name.
- * MDB2_FETCHMODE_FLIPPED switches this order, so the first level of arrays
- * is the column name, and the second level the row number.
- */
- define('MDB2_FETCHMODE_FLIPPED', 4);
- // }}}
- // {{{ Portability mode constants
- /**
- * Portability: turn off all portability features.
- * @see MDB2_Driver_Common::setOption()
- */
- define('MDB2_PORTABILITY_NONE', 0);
- /**
- * Portability: convert names of tables and fields to case defined in the
- * "field_case" option when using the query*(), fetch*() and tableInfo() methods.
- * @see MDB2_Driver_Common::setOption()
- */
- define('MDB2_PORTABILITY_FIX_CASE', 1);
- /**
- * Portability: right trim the data output by query*() and fetch*().
- * @see MDB2_Driver_Common::setOption()
- */
- define('MDB2_PORTABILITY_RTRIM', 2);
- /**
- * Portability: force reporting the number of rows deleted.
- * @see MDB2_Driver_Common::setOption()
- */
- define('MDB2_PORTABILITY_DELETE_COUNT', 4);
- /**
- * Portability: not needed in MDB2 (just left here for compatibility to DB)
- * @see MDB2_Driver_Common::setOption()
- */
- define('MDB2_PORTABILITY_NUMROWS', 8);
- /**
- * Portability: makes certain error messages in certain drivers compatible
- * with those from other DBMS's.
- *
- * + mysql, mysqli: change unique/primary key constraints
- * MDB2_ERROR_ALREADY_EXISTS -> MDB2_ERROR_CONSTRAINT
- *
- * + odbc(access): MS's ODBC driver reports 'no such field' as code
- * 07001, which means 'too few parameters.' When this option is on
- * that code gets mapped to MDB2_ERROR_NOSUCHFIELD.
- *
- * @see MDB2_Driver_Common::setOption()
- */
- define('MDB2_PORTABILITY_ERRORS', 16);
- /**
- * Portability: convert empty values to null strings in data output by
- * query*() and fetch*().
- * @see MDB2_Driver_Common::setOption()
- */
- define('MDB2_PORTABILITY_EMPTY_TO_NULL', 32);
- /**
- * Portability: removes database/table qualifiers from associative indexes
- * @see MDB2_Driver_Common::setOption()
- */
- define('MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES', 64);
- /**
- * Portability: turn on all portability features.
- * @see MDB2_Driver_Common::setOption()
- */
- define('MDB2_PORTABILITY_ALL', 127);
- // }}}
- // {{{ Globals for class instance tracking
- /**
- * These are global variables that are used to track the various class instances
- */
- $GLOBALS['_MDB2_databases'] = array();
- $GLOBALS['_MDB2_dsninfo_default'] = array(
- 'phptype' => false,
- 'dbsyntax' => false,
- 'username' => false,
- 'password' => false,
- 'protocol' => false,
- 'hostspec' => false,
- 'port' => false,
- 'socket' => false,
- 'database' => false,
- 'mode' => false,
- );
- // }}}
- // {{{ class MDB2
- /**
- * The main 'MDB2' class is simply a container class with some static
- * methods for creating DB objects as well as some utility functions
- * common to all parts of DB.
- *
- * The object model of MDB2 is as follows (indentation means inheritance):
- *
- * MDB2 The main MDB2 class. This is simply a utility class
- * with some 'static' methods for creating MDB2 objects as
- * well as common utility functions for other MDB2 classes.
- *
- * MDB2_Driver_Common The base for each MDB2 implementation. Provides default
- * | implementations (in OO lingo virtual methods) for
- * | the actual DB implementations as well as a bunch of
- * | query utility functions.
- * |
- * +-MDB2_Driver_mysql The MDB2 implementation for MySQL. Inherits MDB2_Driver_Common.
- * When calling MDB2::factory or MDB2::connect for MySQL
- * connections, the object returned is an instance of this
- * class.
- * +-MDB2_Driver_pgsql The MDB2 implementation for PostGreSQL. Inherits MDB2_Driver_Common.
- * When calling MDB2::factory or MDB2::connect for PostGreSQL
- * connections, the object returned is an instance of this
- * class.
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith <smith@pooteeweet.org>
- */
- class MDB2
- {
- // {{{ function setOptions(&$db, $options)
- /**
- * set option array in an exiting database object
- *
- * @param MDB2_Driver_Common MDB2 object
- * @param array An associative array of option names and their values.
- *
- * @return mixed MDB2_OK or a PEAR Error object
- *
- * @access public
- */
- function setOptions(&$db, $options)
- {
- if (is_array($options)) {
- foreach ($options as $option => $value) {
- $test = $db->setOption($option, $value);
- if (PEAR::isError($test)) {
- return $test;
- }
- }
- }
- return MDB2_OK;
- }
- // }}}
- // {{{ function classExists($classname)
- /**
- * Checks if a class exists without triggering __autoload
- *
- * @param string classname
- *
- * @return bool true success and false on error
- * @static
- * @access public
- */
- function classExists($classname)
- {
- if (version_compare(phpversion(), "5.0", ">=")) {
- return class_exists($classname, false);
- }
- return class_exists($classname);
- }
- // }}}
- // {{{ function loadClass($class_name, $debug)
- /**
- * Loads a PEAR class.
- *
- * @param string classname to load
- * @param bool if errors should be suppressed
- *
- * @return mixed true success or PEAR_Error on failure
- *
- * @access public
- */
- function loadClass($class_name, $debug)
- {
- if (!MDB2::classExists($class_name)) {
- $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php';
- if ($debug) {
- $include = include_once($file_name);
- } else {
- $include = @include_once($file_name);
- }
- if (!$include) {
- if (!MDB2::fileExists($file_name)) {
- $msg = "unable to find package '$class_name' file '$file_name'";
- } else {
- $msg = "unable to load class '$class_name' from file '$file_name'";
- }
- $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
- return $err;
- }
- }
- return MDB2_OK;
- }
- // }}}
- // {{{ 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.
- * 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 object, or false on error
- *
- * @access public
- */
- function &factory($dsn, $options = false)
- {
- $dsninfo = MDB2::parseDSN($dsn);
- if (empty($dsninfo['phptype'])) {
- $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND,
- null, null, 'no RDBMS driver specified');
- return $err;
- }
- $class_name = 'MDB2_Driver_'.$dsninfo['phptype'];
- $debug = (!empty($options['debug']));
- $err = MDB2::loadClass($class_name, $debug);
- if (PEAR::isError($err)) {
- return $err;
- }
- $db =& new $class_name();
- $db->setDSN($dsninfo);
- $err = MDB2::setOptions($db, $options);
- if (PEAR::isError($err)) {
- return $err;
- }
- return $db;
- }
- // }}}
- // {{{ function &connect($dsn, $options = false)
- /**
- * Create a new MDB2 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).
- *
- * 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
- *
- * @access public
- * @see MDB2::parseDSN
- */
- function &connect($dsn, $options = false)
- {
- $db =& MDB2::factory($dsn, $options);
- if (PEAR::isError($db)) {
- return $db;
- }
- $err = $db->connect();
- if (PEAR::isError($err)) {
- $dsn = $db->getDSN('string', 'xxx');
- $db->disconnect();
- $err->addUserInfo($dsn);
- return $err;
- }
- return $db;
- }
- // }}}
- // {{{ 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.
- * 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
- *
- * @access public
- * @see MDB2::parseDSN
- */
- function &singleton($dsn = null, $options = false)
- {
- if ($dsn) {
- $dsninfo = MDB2::parseDSN($dsn);
- $dsninfo = array_merge($GLOBALS['_MDB2_dsninfo_default'], $dsninfo);
- $keys = array_keys($GLOBALS['_MDB2_databases']);
- for ($i=0, $j=count($keys); $i<$j; ++$i) {
- if (isset($GLOBALS['_MDB2_databases'][$keys[$i]])) {
- $tmp_dsn = $GLOBALS['_MDB2_databases'][$keys[$i]]->getDSN('array');
- if (count(array_diff_assoc($tmp_dsn, $dsninfo)) == 0) {
- MDB2::setOptions($GLOBALS['_MDB2_databases'][$keys[$i]], $options);
- return $GLOBALS['_MDB2_databases'][$keys[$i]];
- }
- }
- }
- } elseif (is_array($GLOBALS['_MDB2_databases']) && reset($GLOBALS['_MDB2_databases'])) {
- $db =& $GLOBALS['_MDB2_databases'][key($GLOBALS['_MDB2_databases'])];
- return $db;
- }
- $db =& MDB2::factory($dsn, $options);
- return $db;
- }
- // }}}
- // {{{ function loadFile($file)
- /**
- * load a file (like 'Date')
- *
- * @param string name of the file in the MDB2 directory (without '.php')
- *
- * @return string name of the file that was included
- *
- * @access public
- */
- function loadFile($file)
- {
- $file_name = 'MDB2'.DIRECTORY_SEPARATOR.$file.'.php';
- if (!MDB2::fileExists($file_name)) {
- return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'unable to find: '.$file_name);
- }
- if (!include_once($file_name)) {
- return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'unable to load driver class: '.$file_name);
- }
- return $file_name;
- }
- // }}}
- // {{{ function apiVersion()
- /**
- * Return the MDB2 API version
- *
- * @return string the MDB2 API version number
- *
- * @access public
- */
- function apiVersion()
- {
- return '2.4.1';
- }
- // }}}
- // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
- /**
- * This method is used to communicate an error and invoke error
- * callbacks etc. Basically a wrapper for PEAR::raiseError
- * without the message string.
- *
- * @param mixed int error code
- *
- * @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.
- *
- * @return PEAR_Error instance of a PEAR Error object
- *
- * @access private
- * @see PEAR_Error
- */
- function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
- {
- $err =& PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
- return $err;
- }
- // }}}
- // {{{ function isError($data, $code = null)
- /**
- * Tell whether a value is a MDB2 error.
- *
- * @param mixed the value to test
- * @param int if is an error object, return true
- * only if $code is a string and
- * $db->getMessage() == $code or
- * $code is an integer and $db->getCode() == $code
- *
- * @return bool true if parameter is an error
- *
- * @access public
- */
- function isError($data, $code = null)
- {
- if (is_a($data, 'MDB2_Error')) {
- if (is_null($code)) {
- return true;
- } elseif (is_string($code)) {
- return $data->getMessage() === $code;
- } else {
- $code = (array)$code;
- return in_array($data->getCode(), $code);
- }
- }
- return false;
- }
- // }}}
- // {{{ function isConnection($value)
- /**
- * Tell whether a value is a MDB2 connection
- *
- * @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');
- }
- // }}}
- // {{{ function isResult($value)
- /**
- * Tell whether a value is a MDB2 result
- *
- * @param mixed value to test
- *
- * @return bool whether $value is a MDB2 result
- *
- * @access public
- */
- function isResult($value)
- {
- return is_a($value, 'MDB2_Result');
- }
- // }}}
- // {{{ function isResultCommon($value)
- /**
- * Tell whether a value is a MDB2 result implementing the common interface
- *
- * @param mixed value to test
- *
- * @return bool whether $value is a MDB2 result implementing the common interface
- *
- * @access public
- */
- function isResultCommon($value)
- {
- return is_a($value, 'MDB2_Result_Common');
- }
- // }}}
- // {{{ function isStatement($value)
- /**
- * Tell whether a value is a MDB2 statement interface
- *
- * @param mixed value to test
- *
- * @return bool whether $value is a MDB2 statement interface
- *
- * @access public
- */
- function isStatement($value)
- {
- return is_a($value, 'MDB2_Statement');
- }
- // }}}
- // {{{ function errorMessage($value = null)
- /**
- * Return a textual error message for a MDB2 error code
- *
- * @param int|array integer error code,
- null to get the current error code-message map,
- or an array with a new error code-message map
- *
- * @return string error message, or false if the error code was
- * not recognized
- *
- * @access public
- */
- function errorMessage($value = null)
- {
- static $errorMessages;
- if (is_array($value)) {
- $errorMessages = $value;
- return MDB2_OK;
- }
- if (!isset($errorMessages)) {
- $errorMessages = array(
- MDB2_OK => 'no error',
- MDB2_ERROR => 'unknown error',
- MDB2_ERROR_ALREADY_EXISTS => 'already exists',
- MDB2_ERROR_CANNOT_CREATE => 'can not create',
- MDB2_ERROR_CANNOT_ALTER => 'can not alter',
- MDB2_ERROR_CANNOT_REPLACE => 'can not replace',
- MDB2_ERROR_CANNOT_DELETE => 'can not delete',
- MDB2_ERROR_CANNOT_DROP => 'can not drop',
- MDB2_ERROR_CONSTRAINT => 'constraint violation',
- MDB2_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
- MDB2_ERROR_DIVZERO => 'division by zero',
- MDB2_ERROR_INVALID => 'invalid',
- MDB2_ERROR_INVALID_DATE => 'invalid date or time',
- MDB2_ERROR_INVALID_NUMBER => 'invalid number',
- MDB2_ERROR_MISMATCH => 'mismatch',
- MDB2_ERROR_NODBSELECTED => 'no database selected',
- MDB2_ERROR_NOSUCHFIELD => 'no such field',
- MDB2_ERROR_NOSUCHTABLE => 'no such table',
- MDB2_ERROR_NOT_CAPABLE => 'MDB2 backend not capable',
- MDB2_ERROR_NOT_FOUND => 'not found',
- MDB2_ERROR_NOT_LOCKED => 'not locked',
- MDB2_ERROR_SYNTAX => 'syntax error',
- MDB2_ERROR_UNSUPPORTED => 'not supported',
- MDB2_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
- MDB2_ERROR_INVALID_DSN => 'invalid DSN',
- MDB2_ERROR_CONNECT_FAILED => 'connect failed',
- MDB2_ERROR_NEED_MORE_DATA => 'insufficient data supplied',
- MDB2_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
- MDB2_ERROR_NOSUCHDB => 'no such database',
- MDB2_ERROR_ACCESS_VIOLATION => 'insufficient permissions',
- MDB2_ERROR_LOADMODULE => 'error while including on demand module',
- MDB2_ERROR_TRUNCATED => 'truncated',
- MDB2_ERROR_DEADLOCK => 'deadlock detected',
- );
- }
- if (is_null($value)) {
- return $errorMessages;
- }
- if (PEAR::isError($value)) {
- $value = $value->getCode();
- }
- return isset($errorMessages[$value]) ?
- $errorMessages[$value] : $errorMessages[MDB2_ERROR];
- }
- // }}}
- // {{{ function parseDSN($dsn)
- /**
- * Parse a data source name.
- *
- * Additional keys can be added by appending a URI query string to the
- * end of the DSN.
- *
- * The format of the supplied DSN is in its fullest form:
- * <code>
- * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
- * </code>
- *
- * Most variations are allowed:
- * <code>
- * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
- * phptype://username:password@hostspec/database_name
- * phptype://username:password@hostspec
- * phptype://username@hostspec
- * phptype://hostspec/database
- * phptype://hostspec
- * phptype(dbsyntax)
- * phptype
- * </code>
- *
- * @param string Data Source Name to be parsed
- *
- * @return array an associative array with the following keys:
- * + phptype: Database backend used in PHP (mysql, odbc etc.)
- * + dbsyntax: Database used with regards to SQL syntax etc.
- * + protocol: Communication protocol to use (tcp, unix etc.)
- * + hostspec: Host specification (hostname[:port])
- * + database: Database to use on the DBMS server
- * + username: User name for login
- * + password: Password for login
- *
- * @access public
- * @author Tomas V.V.Cox <cox@idecnet.com>
- */
- function parseDSN($dsn)
- {
- $parsed = $GLOBALS['_MDB2_dsninfo_default'];
- if (is_array($dsn)) {
- $dsn = array_merge($parsed, $dsn);
- if (!$dsn['dbsyntax']) {
- $dsn['dbsyntax'] = $dsn['phptype'];
- }
- return $dsn;
- }
- // Find phptype and dbsyntax
- if (($pos = strpos($dsn, '://')) !== false) {
- $str = substr($dsn, 0, $pos);
- $dsn = substr($dsn, $pos + 3);
- } else {
- $str = $dsn;
- $dsn = null;
- }
- // Get phptype and dbsyntax
- // $str => phptype(dbsyntax)
- if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
- $parsed['phptype'] = $arr[1];
- $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
- } else {
- $parsed['phptype'] = $str;
- $parsed['dbsyntax'] = $str;
- }
- if (!count($dsn)) {
- return $parsed;
- }
- // Get (if found): username and password
- // $dsn => username:password@protocol+hostspec/database
- if (($at = strrpos($dsn,'@')) !== false) {
- $str = substr($dsn, 0, $at);
- $dsn = substr($dsn, $at + 1);
- if (($pos = strpos($str, ':')) !== false) {
- $parsed['username'] = rawurldecode(substr($str, 0, $pos));
- $parsed['password'] = rawurldecode(substr($str, $pos + 1));
- } else {
- $parsed['username'] = rawurldecode($str);
- }
- }
- // Find protocol and hostspec
- // $dsn => proto(proto_opts)/database
- if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
- $proto = $match[1];
- $proto_opts = $match[2] ? $match[2] : false;
- $dsn = $match[3];
- // $dsn => protocol+hostspec/database (old format)
- } else {
- if (strpos($dsn, '+') !== false) {
- list($proto, $dsn) = explode('+', $dsn, 2);
- }
- if ( strpos($dsn, '//') === 0
- && strpos($dsn, '/', 2) !== false
- && $parsed['phptype'] == 'oci8'
- ) {
- //oracle's "Easy Connect" syntax:
- //"username/password@[//]host[:port][/service_name]"
- //e.g. "scott/tiger@//mymachine:1521/oracle"
- $proto_opts = $dsn;
- $dsn = null;
- } elseif (strpos($dsn, '/') !== false) {
- list($proto_opts, $dsn) = explode('/', $dsn, 2);
- } else {
- $proto_opts = $dsn;
- $dsn = null;
- }
- }
- // 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') {
- $parsed['hostspec'] = $proto_opts;
- } elseif ($parsed['protocol'] == 'unix') {
- $parsed['socket'] = $proto_opts;
- }
- // Get dabase if any
- // $dsn => database
- if ($dsn) {
- // /database
- if (($pos = strpos($dsn, '?')) === false) {
- $parsed['database'] = $dsn;
- // /database?param1=value1¶m2=value2
- } else {
- $parsed['database'] = substr($dsn, 0, $pos);
- $dsn = substr($dsn, $pos + 1);
- if (strpos($dsn, '&') !== false) {
- $opts = explode('&', $dsn);
- } else { // database?param1=value1
- $opts = array($dsn);
- }
- foreach ($opts as $opt) {
- list($key, $value) = explode('=', $opt);
- if (!isset($parsed[$key])) {
- // don't allow params overwrite
- $parsed[$key] = rawurldecode($value);
- }
- }
- }
- }
- return $parsed;
- }
- // }}}
- // {{{ function fileExists($file)
- /**
- * Checks if a file exists in the include path
- *
- * @param string filename
- *
- * @return bool true success and false on error
- *
- * @access public
- */
- function fileExists($file)
- {
- // safe_mode does notwork with is_readable()
- if (!@ini_get('safe_mode')) {
- $dirs = explode(PATH_SEPARATOR, ini_get('include_path'));
- foreach ($dirs as $dir) {
- if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) {
- return true;
- }
- }
- } else {
- $fp = @fopen($file, 'r', true);
- if (is_resource($fp)) {
- @fclose($fp);
- return true;
- }
- }
- return false;
- }
- // }}}
- }
- // }}}
- // {{{ class MDB2_Error extends PEAR_Error
- /**
- * MDB2_Error implements a class for reporting portable database error
- * messages.
- *
- * @package MDB2
- * @category Database
- * @author Stig Bakken <ssb@fast.no>
- */
- class MDB2_Error extends PEAR_Error
- {
- // {{{ constructor: function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null)
- /**
- * MDB2_Error constructor.
- *
- * @param mixed MDB2 error code, or string with error message.
- * @param int what 'error mode' to operate in
- * @param int what error level to use for $mode & PEAR_ERROR_TRIGGER
- * @param smixed additional debug info, such as the last query
- */
- function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN,
- $level = E_USER_NOTICE, $debuginfo = null)
- {
- if (is_null($code)) {
- $code = MDB2_ERROR;
- }
- $this->PEAR_Error('MDB2 Error: '.MDB2::errorMessage($code), $code,
- $mode, $level, $debuginfo);
- }
- // }}}
- }
- // }}}
- // {{{ class MDB2_Driver_Common extends PEAR
- /**
- * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith <smith@pooteeweet.org>
- */
- class MDB2_Driver_Common extends PEAR
- {
- // {{{ Variables (Properties)
- /**
- * index of the MDB2 object within the $GLOBALS['_MDB2_databases'] array
- * @var int
- * @access public
- */
- var $db_index = 0;
- /**
- * DSN used for the next query
- * @var array
- * @access protected
- */
- var $dsn = array();
- /**
- * DSN that was used to create the current connection
- * @var array
- * @access protected
- */
- var $connected_dsn = array();
- /**
- * connection resource
- * @var mixed
- * @access protected
- */
- var $connection = 0;
- /**
- * if the current opened connection is a persistent connection
- * @var bool
- * @access protected
- */
- var $opened_persistent;
- /**
- * the name of the database for the next query
- * @var string
- * @access protected
- */
- var $database_name = '';
- /**
- * the name of the database currently selected
- * @var string
- * @access protected
- */
- var $connected_database_name = '';
- /**
- * server version information
- * @var string
- * @access protected
- */
- var $connected_server_info = '';
- /**
- * list of all supported features of the given driver
- * @var array
- * @access public
- */
- var $supported = array(
- 'sequences' => false,
- 'indexes' => false,
- 'affected_rows' => false,
- 'summary_functions' => false,
- 'order_by_text' => false,
- 'transactions' => false,
- 'savepoints' => false,
- 'current_id' => false,
- 'limit_queries' => false,
- 'LOBs' => false,
- 'replace' => false,
- 'sub_selects' => false,
- 'auto_increment' => false,
- 'primary_key' => false,
- 'result_introspection' => false,
- 'prepared_statements' => false,
- 'identifier_quoting' => false,
- 'pattern_escaping' => false,
- 'new_link' => false,
- );
- /**
- * Array of supported options that can be passed to the MDB2 instance.
- *
- * The options can be set during object creation, using
- * MDB2::connect(), MDB2::factory() or MDB2::singleton(). The options can
- * also be set after the object is created, using MDB2::setOptions() or
- * MDB2_Driver_Common::setOption().
- * The list of available option includes:
- * <ul>
- * <li>$options['ssl'] -> boolean: determines if ssl should be used for connections</li>
- * <li>$options['field_case'] -> CASE_LOWER|CASE_UPPER: determines what case to force on field/table names</li>
- * <li>$options['disable_query'] -> boolean: determines if queries should be executed</li>
- * <li>$options['result_class'] -> string: class used for result sets</li>
- * <li>$options['buffered_result_class'] -> string: class used for buffered result sets</li>
- * <li>$options['result_wrap_class'] -> string: class used to wrap result sets into</li>
- * <li>$options['result_buffering'] -> boolean should results be buffered or not?</li>
- * <li>$options['fetch_class'] -> string: class to use when fetch mode object is used</li>
- * <li>$options['persistent'] -> boolean: persistent connection?</li>
- * <li>$options['debug'] -> integer: numeric debug level</li>
- * <li>$options['debug_handler'] -> string: function/method that captures debug messages</li>
- * <li>$options['debug_expanded_output'] -> bool: BC option to determine if more context information should be send to the debug handler</li>
- * <li>$options['default_text_field_length'] -> integer: default text field length to use</li>
- * <li>$options['lob_buffer_length'] -> integer: LOB buffer length</li>
- * <li>$options['log_line_break'] -> string: line-break format</li>
- * <li>$options['idxname_format'] -> string: pattern for index name</li>
- * <li>$options['seqname_format'] -> string: pattern for sequence name</li>
- * <li>$options['savepoint_format'] -> string: pattern for auto generated savepoint names</li>
- * <li>$options['statement_format'] -> string: pattern for prepared statement names</li>
- * <li>$options['seqcol_name'] -> string: sequence column name</li>
- * <li>$options['quote_identifier'] -> boolean: if identifier quoting should be done when check_option is used</li>
- * <li>$options['use_transactions'] -> boolean: if transaction use should be enabled</li>
- * <li>$options['decimal_places'] -> integer: number of decimal places to handle</li>
- * <li>$options['portability'] -> integer: portability constant</li>
- * <li>$options['modules'] -> array: short to long module name mapping for __call()</li>
- * <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>
- * </ul>
- *
- * @var array
- * @access public
- * @see MDB2::connect()
- * @see MDB2::factory()
- * @see MDB2::singleton()
- * @see MDB2_Driver_Common::setOption()
- */
- var $options = array(
- 'ssl' => false,
- 'field_case' => CASE_LOWER,
- 'disable_query' => false,
- 'result_class' => 'MDB2_Result_%s',
- 'buffered_result_class' => 'MDB2_BufferedResult_%s',
- 'result_wrap_class' => false,
- 'result_buffering' => true,
- 'fetch_class' => 'stdClass',
- 'persistent' => false,
- 'debug' => 0,
- 'debug_handler' => 'MDB2_defaultDebugOutput',
- 'debug_expanded_output' => false,
- 'default_text_field_length' => 4096,
- 'lob_buffer_length' => 8192,
- 'log_line_break' => "\n",
- 'idxname_format' => '%s_idx',
- 'seqname_format' => '%s_seq',
- 'savepoint_format' => 'MDB2_SAVEPOINT_%s',
- 'statement_format' => 'MDB2_STATEMENT_%1$s_%2$s',
- 'seqcol_name' => 'sequence',
- 'quote_identifier' => false,
- 'use_transactions' => true,
- 'decimal_places' => 2,
- 'portability' => MDB2_PORTABILITY_ALL,
- 'modules' => array(
- 'ex' => 'Extended',
- 'dt' => 'Datatype',
- 'mg' => 'Manager',
- 'rv' => 'Reverse',
- 'na' => 'Native',
- 'fc' => 'Function',
- ),
- 'emulate_prepared' => false,
- 'datatype_map' => array(),
- 'datatype_map_callback' => array(),
- 'nativetype_map_callback' => array(),
- );
- /**
- * string array
- * @var string
- * @access protected
- */
- var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => false, 'escape_pattern' => false);
- /**
- * identifier quoting
- * @var array
- * @access protected
- */
- var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"');
- /**
- * sql comments
- * @var array
- * @access protected
- */
- var $sql_comments = array(
- array('start' => '--', 'end' => "\n", 'escape' => false),
- array('start' => '/*', 'end' => '*/', 'escape' => false),
- );
- /**
- * comparision wildcards
- * @var array
- * @access protected
- */
- var $wildcards = array('%', '_');
- /**
- * column alias keyword
- * @var string
- * @access protected
- */
- var $as_keyword = ' AS ';
- /**
- * warnings
- * @var array
- * @access protected
- */
- var $warnings = array();
- /**
- * string with the debugging information
- * @var string
- * @access public
- */
- var $debug_output = '';
- /**
- * determine if there is an open transaction
- * @var bool
- * @access protected
- */
- var $in_transaction = false;
- /**
- * the smart transaction nesting depth
- * @var int
- * @access protected
- */
- var $nested_transaction_counter = null;
- /**
- * the first error that occured inside a nested transaction
- * @var MDB2_Error|bool
- * @access protected
- */
- var $has_transaction_error = false;
- /**
- * result offset used in the next query
- * @var int
- * @access protected
- */
- var $offset = 0;
- /**
- * result limit used in the next query
- * @var int
- * @access protected
- */
- var $limit = 0;
- /**
- * Database backend used in PHP (mysql, odbc etc.)
- * @var string
- * @access public
- */
- var $phptype;
- /**
- * Database used with regards to SQL syntax etc.
- * @var string
- * @access public
- */
- var $dbsyntax;
- /**
- * the last query sent to the driver
- * @var string
- * @access public
- */
- var $last_query;
- /**
- * the default fetchmode used
- * @var int
- * @access protected
- */
- var $fetchmode = MDB2_FETCHMODE_ORDERED;
- /**
- * array of module instances
- * @var array
- * @access protected
- */
- var $modules = array();
- /**
- * determines of the PHP4 destructor emulation has been enabled yet
- * @var array
- * @access protected
- */
- var $destructor_registered = true;
- // }}}
- // {{{ constructor: function __construct()
- /**
- * Constructor
- */
- function __construct()
- {
- end($GLOBALS['_MDB2_databases']);
- $db_index = key($GLOBALS['_MDB2_databases']) + 1;
- $GLOBALS['_MDB2_databases'][$db_index] = &$this;
- $this->db_index = $db_index;
- }
- // }}}
- // {{{ function MDB2_Driver_Common()
- /**
- * PHP 4 Constructor
- */
- function MDB2_Driver_Common()
- {
- $this->destructor_registered = false;
- $this->__construct();
- }
- // }}}
- // {{{ destructor: function __destruct()
- /**
- * Destructor
- */
- function __destruct()
- {
- $this->disconnect(false);
- }
- // }}}
- // {{{ function free()
- /**
- * Free the internal references so that the instance can be destroyed
- *
- * @return bool true on success, false if result is invalid
- *
- * @access public
- */
- function free()
- {
- unset($GLOBALS['_MDB2_databases'][$this->db_index]);
- unset($this->db_index);
- return MDB2_OK;
- }
- // }}}
- // {{{ function __toString()
- /**
- * String conversation
- *
- * @return string representation of the object
- *
- * @access public
- */
- function __toString()
- {
- $info = get_class($this);
- $info.= ': (phptype = '.$this->phptype.', dbsyntax = '.$this->dbsyntax.')';
- if ($this->connection) {
- $info.= ' [connected]';
- }
- return $info;
- }
- // }}}
- // {{{ function errorInfo($error = null)
- /**
- * This method is used to collect information about an error
- *
- * @param mixed error code or resource
- *
- * @return array with MDB2 errorcode, native error code, native message
- *
- * @access public
- */
- function errorInfo($error = null)
- {
- return array($error, null, null);
- }
- // }}}
- // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
- /**
- * This method is used to communicate an error and invoke error
- * 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
- *
- * @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)
- {
- $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)) {
- $mode = $this->_default_error_mode;
- $options = $this->_default_error_options;
- }
- if (is_null($userinfo)) {
- $userinfo = $code->getUserinfo();
- }
- $code = $code->getCode();
- } elseif ($code == MDB2_ERROR_NOT_FOUND) {
- // extension not loaded: don't call $this->errorInfo() or the script
- // will die
- } elseif (isset($this->connection)) {
- if (!empty($this->last_query)) {
- $userinfo.= "[Last executed query: {$this->last_query}]\n";
- }
- $native_errno = $native_msg = null;
- list($code, $native_errno, $native_msg) = $this->errorInfo($code);
- if (!is_null($native_errno) && $native_errno !== '') {
- $userinfo.= "[Native code: $native_errno]\n";
- }
- if (!is_null($native_msg) && $native_msg !== '') {
- $userinfo.= "[Native message: ". strip_tags($native_msg) ."]\n";
- }
- if (!is_null($method)) {
- $userinfo = $method.': '.$userinfo;
- }
- }
- $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;
- }
- return $err;
- }
- // }}}
- // {{{ function resetWarnings()
- /**
- * reset the warning array
- *
- * @return void
- *
- * @access public
- */
- function resetWarnings()
- {
- $this->warnings = array();
- }
- // }}}
- // {{{ function getWarnings()
- /**
- * Get all warnings in reverse order.
- * This means that the last warning is the first element in the array
- *
- * @return array with warnings
- *
- * @access public
- * @see resetWarnings()
- */
- function getWarnings()
- {
- return array_reverse($this->warnings);
- }
- // }}}
- // {{{ function setFetchMode($fetchmode, $object_class = 'stdClass')
- /**
- * Sets which fetch mode should be used by default on queries
- * on this connection
- *
- * @param int MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC
- * or MDB2_FETCHMODE_OBJECT
- * @param string the class name of the object to be returned
- * by the fetch methods when the
- * MDB2_FETCHMODE_OBJECT mode is selected.
- * If no class is specified by default a cast
- * to object from the assoc array row will be
- * done. There is also the possibility to use
- * and extend the 'MDB2_row' class.
- *
- * @return mixed MDB2_OK or MDB2 Error Object
- *
- * @access public
- * @see MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC, MDB2_FETCHMODE_OBJECT
- */
- function setFetchMode($fetchmode, $object_class = 'stdClass')
- {
- switch ($fetchmode) {
- case MDB2_FETCHMODE_OBJECT:
- $this->options['fetch_class'] = $object_class;
- case MDB2_FETCHMODE_ORDERED:
- case MDB2_FETCHMODE_ASS…
Large files files are truncated, but you can click here to view the full file