PageRenderTime 79ms CodeModel.GetById 42ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 1ms

/j/kfm/includes/pear/MDB2.php

http://kv-webme.googlecode.com/
PHP | 4213 lines | 1819 code | 364 blank | 2030 comment | 298 complexity | 06a8b49acaf098294725b4810de586cd MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2// vim: set et ts=4 sw=4 fdm=marker:
   3// +----------------------------------------------------------------------+
   4// | PHP versions 4 and 5                                                 |
   5// +----------------------------------------------------------------------+
   6// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
   7// | Stig. S. Bakken, Lukas Smith                                         |
   8// | All rights reserved.                                                 |
   9// +----------------------------------------------------------------------+
  10// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
  11// | API as well as database abstraction for PHP applications.            |
  12// | This LICENSE is in the BSD license style.                            |
  13// |                                                                      |
  14// | Redistribution and use in source and binary forms, with or without   |
  15// | modification, are permitted provided that the following conditions   |
  16// | are met:                                                             |
  17// |                                                                      |
  18// | Redistributions of source code must retain the above copyright       |
  19// | notice, this list of conditions and the following disclaimer.        |
  20// |                                                                      |
  21// | Redistributions in binary form must reproduce the above copyright    |
  22// | notice, this list of conditions and the following disclaimer in the  |
  23// | documentation and/or other materials provided with the distribution. |
  24// |                                                                      |
  25// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  26// | Lukas Smith nor the names of his contributors may be used to endorse |
  27// | or promote products derived from this software without specific prior|
  28// | written permission.                                                  |
  29// |                                                                      |
  30// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  31// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  32// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  33// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  34// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  35// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  36// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  37// |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  38// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  39// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  40// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  41// | POSSIBILITY OF SUCH DAMAGE.                                          |
  42// +----------------------------------------------------------------------+
  43// | Author: Lukas Smith <smith@pooteeweet.org>                           |
  44// +----------------------------------------------------------------------+
  45//
  46// $Id: MDB2.php,v 1.292 2007/04/25 09:31:01 quipo Exp $
  47//
  48
  49/**
  50 * @package     MDB2
  51 * @category    Database
  52 * @author      Lukas Smith <smith@pooteeweet.org>
  53 */
  54
  55require_once 'PEAR.php';
  56
  57// {{{ Error constants
  58
  59/**
  60 * The method mapErrorCode in each MDB2_dbtype implementation maps
  61 * native error codes to one of these.
  62 *
  63 * If you add an error code here, make sure you also add a textual
  64 * version of it in MDB2::errorMessage().
  65 */
  66
  67define('MDB2_OK',                      true);
  68define('MDB2_ERROR',                     -1);
  69define('MDB2_ERROR_SYNTAX',              -2);
  70define('MDB2_ERROR_CONSTRAINT',          -3);
  71define('MDB2_ERROR_NOT_FOUND',           -4);
  72define('MDB2_ERROR_ALREADY_EXISTS',      -5);
  73define('MDB2_ERROR_UNSUPPORTED',         -6);
  74define('MDB2_ERROR_MISMATCH',            -7);
  75define('MDB2_ERROR_INVALID',             -8);
  76define('MDB2_ERROR_NOT_CAPABLE',         -9);
  77define('MDB2_ERROR_TRUNCATED',          -10);
  78define('MDB2_ERROR_INVALID_NUMBER',     -11);
  79define('MDB2_ERROR_INVALID_DATE',       -12);
  80define('MDB2_ERROR_DIVZERO',            -13);
  81define('MDB2_ERROR_NODBSELECTED',       -14);
  82define('MDB2_ERROR_CANNOT_CREATE',      -15);
  83define('MDB2_ERROR_CANNOT_DELETE',      -16);
  84define('MDB2_ERROR_CANNOT_DROP',        -17);
  85define('MDB2_ERROR_NOSUCHTABLE',        -18);
  86define('MDB2_ERROR_NOSUCHFIELD',        -19);
  87define('MDB2_ERROR_NEED_MORE_DATA',     -20);
  88define('MDB2_ERROR_NOT_LOCKED',         -21);
  89define('MDB2_ERROR_VALUE_COUNT_ON_ROW', -22);
  90define('MDB2_ERROR_INVALID_DSN',        -23);
  91define('MDB2_ERROR_CONNECT_FAILED',     -24);
  92define('MDB2_ERROR_EXTENSION_NOT_FOUND',-25);
  93define('MDB2_ERROR_NOSUCHDB',           -26);
  94define('MDB2_ERROR_ACCESS_VIOLATION',   -27);
  95define('MDB2_ERROR_CANNOT_REPLACE',     -28);
  96define('MDB2_ERROR_CONSTRAINT_NOT_NULL',-29);
  97define('MDB2_ERROR_DEADLOCK',           -30);
  98define('MDB2_ERROR_CANNOT_ALTER',       -31);
  99define('MDB2_ERROR_MANAGER',            -32);
 100define('MDB2_ERROR_MANAGER_PARSE',      -33);
 101define('MDB2_ERROR_LOADMODULE',         -34);
 102define('MDB2_ERROR_INSUFFICIENT_DATA',  -35);
 103// }}}
 104// {{{ Verbose constants
 105/**
 106 * These are just helper constants to more verbosely express parameters to prepare()
 107 */
 108
 109define('MDB2_PREPARE_MANIP', false);
 110define('MDB2_PREPARE_RESULT', null);
 111
 112// }}}
 113// {{{ Fetchmode constants
 114
 115/**
 116 * This is a special constant that tells MDB2 the user hasn't specified
 117 * any particular get mode, so the default should be used.
 118 */
 119define('MDB2_FETCHMODE_DEFAULT', 0);
 120
 121/**
 122 * Column data indexed by numbers, ordered from 0 and up
 123 */
 124define('MDB2_FETCHMODE_ORDERED', 1);
 125
 126/**
 127 * Column data indexed by column names
 128 */
 129define('MDB2_FETCHMODE_ASSOC', 2);
 130
 131/**
 132 * Column data as object properties
 133 */
 134define('MDB2_FETCHMODE_OBJECT', 3);
 135
 136/**
 137 * For multi-dimensional results: normally the first level of arrays
 138 * is the row number, and the second level indexed by column number or name.
 139 * MDB2_FETCHMODE_FLIPPED switches this order, so the first level of arrays
 140 * is the column name, and the second level the row number.
 141 */
 142define('MDB2_FETCHMODE_FLIPPED', 4);
 143
 144// }}}
 145// {{{ Portability mode constants
 146
 147/**
 148 * Portability: turn off all portability features.
 149 * @see MDB2_Driver_Common::setOption()
 150 */
 151define('MDB2_PORTABILITY_NONE', 0);
 152
 153/**
 154 * Portability: convert names of tables and fields to case defined in the
 155 * "field_case" option when using the query*(), fetch*() and tableInfo() methods.
 156 * @see MDB2_Driver_Common::setOption()
 157 */
 158define('MDB2_PORTABILITY_FIX_CASE', 1);
 159
 160/**
 161 * Portability: right trim the data output by query*() and fetch*().
 162 * @see MDB2_Driver_Common::setOption()
 163 */
 164define('MDB2_PORTABILITY_RTRIM', 2);
 165
 166/**
 167 * Portability: force reporting the number of rows deleted.
 168 * @see MDB2_Driver_Common::setOption()
 169 */
 170define('MDB2_PORTABILITY_DELETE_COUNT', 4);
 171
 172/**
 173 * Portability: not needed in MDB2 (just left here for compatibility to DB)
 174 * @see MDB2_Driver_Common::setOption()
 175 */
 176define('MDB2_PORTABILITY_NUMROWS', 8);
 177
 178/**
 179 * Portability: makes certain error messages in certain drivers compatible
 180 * with those from other DBMS's.
 181 *
 182 * + mysql, mysqli:  change unique/primary key constraints
 183 *   MDB2_ERROR_ALREADY_EXISTS -> MDB2_ERROR_CONSTRAINT
 184 *
 185 * + odbc(access):  MS's ODBC driver reports 'no such field' as code
 186 *   07001, which means 'too few parameters.'  When this option is on
 187 *   that code gets mapped to MDB2_ERROR_NOSUCHFIELD.
 188 *
 189 * @see MDB2_Driver_Common::setOption()
 190 */
 191define('MDB2_PORTABILITY_ERRORS', 16);
 192
 193/**
 194 * Portability: convert empty values to null strings in data output by
 195 * query*() and fetch*().
 196 * @see MDB2_Driver_Common::setOption()
 197 */
 198define('MDB2_PORTABILITY_EMPTY_TO_NULL', 32);
 199
 200/**
 201 * Portability: removes database/table qualifiers from associative indexes
 202 * @see MDB2_Driver_Common::setOption()
 203 */
 204define('MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES', 64);
 205
 206/**
 207 * Portability: turn on all portability features.
 208 * @see MDB2_Driver_Common::setOption()
 209 */
 210define('MDB2_PORTABILITY_ALL', 127);
 211
 212// }}}
 213// {{{ Globals for class instance tracking
 214
 215/**
 216 * These are global variables that are used to track the various class instances
 217 */
 218
 219$GLOBALS['_MDB2_databases'] = array();
 220$GLOBALS['_MDB2_dsninfo_default'] = array(
 221    'phptype'  => false,
 222    'dbsyntax' => false,
 223    'username' => false,
 224    'password' => false,
 225    'protocol' => false,
 226    'hostspec' => false,
 227    'port'     => false,
 228    'socket'   => false,
 229    'database' => false,
 230    'mode'     => false,
 231);
 232
 233// }}}
 234// {{{ class MDB2
 235
 236/**
 237 * The main 'MDB2' class is simply a container class with some static
 238 * methods for creating DB objects as well as some utility functions
 239 * common to all parts of DB.
 240 *
 241 * The object model of MDB2 is as follows (indentation means inheritance):
 242 *
 243 * MDB2          The main MDB2 class.  This is simply a utility class
 244 *              with some 'static' methods for creating MDB2 objects as
 245 *              well as common utility functions for other MDB2 classes.
 246 *
 247 * MDB2_Driver_Common   The base for each MDB2 implementation.  Provides default
 248 * |            implementations (in OO lingo virtual methods) for
 249 * |            the actual DB implementations as well as a bunch of
 250 * |            query utility functions.
 251 * |
 252 * +-MDB2_Driver_mysql  The MDB2 implementation for MySQL. Inherits MDB2_Driver_Common.
 253 *              When calling MDB2::factory or MDB2::connect for MySQL
 254 *              connections, the object returned is an instance of this
 255 *              class.
 256 * +-MDB2_Driver_pgsql  The MDB2 implementation for PostGreSQL. Inherits MDB2_Driver_Common.
 257 *              When calling MDB2::factory or MDB2::connect for PostGreSQL
 258 *              connections, the object returned is an instance of this
 259 *              class.
 260 *
 261 * @package     MDB2
 262 * @category    Database
 263 * @author      Lukas Smith <smith@pooteeweet.org>
 264 */
 265class MDB2
 266{
 267    // {{{ function setOptions(&$db, $options)
 268
 269    /**
 270     * set option array   in an exiting database object
 271     *
 272     * @param   MDB2_Driver_Common  MDB2 object
 273     * @param   array   An associative array of option names and their values.
 274     *
 275     * @return mixed   MDB2_OK or a PEAR Error object
 276     *
 277     * @access  public
 278     */
 279    static function setOptions(&$db, $options)
 280    {
 281        if (is_array($options)) {
 282            foreach ($options as $option => $value) {
 283                $test = $db->setOption($option, $value);
 284                if (PEAR::isError($test)) {
 285                    return $test;
 286                }
 287            }
 288        }
 289        return MDB2_OK;
 290    }
 291
 292    // }}}
 293    // {{{ function classExists($classname)
 294
 295    /**
 296     * Checks if a class exists without triggering __autoload
 297     *
 298     * @param   string  classname
 299     *
 300     * @return  bool    true success and false on error
 301     * @static
 302     * @access  public
 303     */
 304    static function classExists($classname)
 305    {
 306        if (version_compare(phpversion(), "5.0", ">=")) {
 307            return class_exists($classname, false);
 308        }
 309        return class_exists($classname);
 310    }
 311
 312    // }}}
 313    // {{{ function loadClass($class_name, $debug)
 314
 315    /**
 316     * Loads a PEAR class.
 317     *
 318     * @param   string  classname to load
 319     * @param   bool    if errors should be suppressed
 320     *
 321     * @return  mixed   true success or PEAR_Error on failure
 322     *
 323     * @access  public
 324     */
 325    static function loadClass($class_name, $debug)
 326    {
 327        if (!MDB2::classExists($class_name)) {
 328            $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php';
 329            $include = include_once($file_name);
 330            if (!$include) {
 331                if (!MDB2::fileExists($file_name)) {
 332                    $msg = "unable to find package '$class_name' file '$file_name'";
 333                } else {
 334                    $msg = "unable to load class '$class_name' from file '$file_name'";
 335                }
 336                $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
 337                return $err;
 338            }
 339        }
 340        return MDB2_OK;
 341    }
 342
 343    // }}}
 344    // {{{ function &factory($dsn, $options = false)
 345
 346    /**
 347     * Create a new MDB2 object for the specified database type
 348     *
 349     * IMPORTANT: In order for MDB2 to work properly it is necessary that
 350     * you make sure that you work with a reference of the original
 351     * object instead of a copy (this is a PHP4 quirk).
 352     *
 353     * For example:
 354     *     $db =& MDB2::factory($dsn);
 355     *          ^^
 356     * And not:
 357     *     $db = MDB2::factory($dsn);
 358     *
 359     * @param   mixed   'data source name', see the MDB2::parseDSN
 360     *                      method for a description of the dsn format.
 361     *                      Can also be specified as an array of the
 362     *                      format returned by MDB2::parseDSN.
 363     * @param   array   An associative array of option names and
 364     *                            their values.
 365     *
 366     * @return  mixed   a newly created MDB2 object, or false on error
 367     *
 368     * @access  public
 369     */
 370    static function &factory($dsn, $options = false)
 371    {
 372        $dsninfo = MDB2::parseDSN($dsn);
 373        if (empty($dsninfo['phptype'])) {
 374            $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND,
 375                null, null, 'no RDBMS driver specified');
 376            return $err;
 377        }
 378        $class_name = 'MDB2_Driver_'.$dsninfo['phptype'];
 379
 380        $debug = (!empty($options['debug']));
 381        $err = MDB2::loadClass($class_name, $debug);
 382        if (PEAR::isError($err)) {
 383            return $err;
 384        }
 385
 386        $db =new $class_name();
 387        $db->setDSN($dsninfo);
 388        $err = MDB2::setOptions($db, $options);
 389        if (PEAR::isError($err)) {
 390            return $err;
 391        }
 392
 393        return $db;
 394    }
 395
 396    // }}}
 397    // {{{ function &connect($dsn, $options = false)
 398
 399    /**
 400     * Create a new MDB2 connection object and connect to the specified
 401     * database
 402     *
 403     * IMPORTANT: In order for MDB2 to work properly it is necessary that
 404     * you make sure that you work with a reference of the original
 405     * object instead of a copy (this is a PHP4 quirk).
 406     *
 407     * For example:
 408     *     $db =& MDB2::connect($dsn);
 409     *          ^^
 410     * And not:
 411     *     $db = MDB2::connect($dsn);
 412     *          ^^
 413     *
 414     * @param   mixed   'data source name', see the MDB2::parseDSN
 415     *                            method for a description of the dsn format.
 416     *                            Can also be specified as an array of the
 417     *                            format returned by MDB2::parseDSN.
 418     * @param   array   An associative array of option names and
 419     *                            their values.
 420     *
 421     * @return  mixed   a newly created MDB2 connection object, or a MDB2
 422     *                  error object on error
 423     *
 424     * @access  public
 425     * @see     MDB2::parseDSN
 426     */
 427    static function &connect($dsn, $options = false)
 428    {
 429        $db =& MDB2::factory($dsn, $options);
 430        if (PEAR::isError($db)) {
 431            return $db;
 432        }
 433
 434        $err = $db->connect();
 435        if (PEAR::isError($err)) {
 436            $dsn = $db->getDSN('string', 'xxx');
 437            $db->disconnect();
 438            $err->addUserInfo($dsn);
 439            return $err;
 440        }
 441
 442        return $db;
 443    }
 444
 445    // }}}
 446    // {{{ function &singleton($dsn = null, $options = false)
 447
 448    /**
 449     * Returns a MDB2 connection with the requested DSN.
 450     * A new MDB2 connection object is only created if no object with the
 451     * requested DSN exists yet.
 452     *
 453     * IMPORTANT: In order for MDB2 to work properly it is necessary that
 454     * you make sure that you work with a reference of the original
 455     * object instead of a copy (this is a PHP4 quirk).
 456     *
 457     * For example:
 458     *     $db =& MDB2::singleton($dsn);
 459     *          ^^
 460     * And not:
 461     *     $db = MDB2::singleton($dsn);
 462     *          ^^
 463     *
 464     * @param   mixed   'data source name', see the MDB2::parseDSN
 465     *                            method for a description of the dsn format.
 466     *                            Can also be specified as an array of the
 467     *                            format returned by MDB2::parseDSN.
 468     * @param   array   An associative array of option names and
 469     *                            their values.
 470     *
 471     * @return  mixed   a newly created MDB2 connection object, or a MDB2
 472     *                  error object on error
 473     *
 474     * @access  public
 475     * @see     MDB2::parseDSN
 476     */
 477    function &singleton($dsn = null, $options = false)
 478    {
 479        if ($dsn) {
 480            $dsninfo = MDB2::parseDSN($dsn);
 481            $dsninfo = array_merge($GLOBALS['_MDB2_dsninfo_default'], $dsninfo);
 482            $keys = array_keys($GLOBALS['_MDB2_databases']);
 483            for ($i=0, $j=count($keys); $i<$j; ++$i) {
 484                if (isset($GLOBALS['_MDB2_databases'][$keys[$i]])) {
 485                    $tmp_dsn = $GLOBALS['_MDB2_databases'][$keys[$i]]->getDSN('array');
 486                    if (count(array_diff_assoc($tmp_dsn, $dsninfo)) == 0) {
 487                        MDB2::setOptions($GLOBALS['_MDB2_databases'][$keys[$i]], $options);
 488                        return $GLOBALS['_MDB2_databases'][$keys[$i]];
 489                    }
 490                }
 491            }
 492        } elseif (is_array($GLOBALS['_MDB2_databases']) && reset($GLOBALS['_MDB2_databases'])) {
 493            $db =& $GLOBALS['_MDB2_databases'][key($GLOBALS['_MDB2_databases'])];
 494            return $db;
 495        }
 496        $db =& MDB2::factory($dsn, $options);
 497        return $db;
 498    }
 499
 500    // }}}
 501    // {{{ function loadFile($file)
 502
 503    /**
 504     * load a file (like 'Date')
 505     *
 506     * @param   string  name of the file in the MDB2 directory (without '.php')
 507     *
 508     * @return  string  name of the file that was included
 509     *
 510     * @access  public
 511     */
 512    function loadFile($file)
 513    {
 514        $file_name = 'MDB2'.DIRECTORY_SEPARATOR.$file.'.php';
 515        if (!MDB2::fileExists($file_name)) {
 516            return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
 517                'unable to find: '.$file_name);
 518        }
 519        if (!include_once($file_name)) {
 520            return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
 521                'unable to load driver class: '.$file_name);
 522        }
 523        return $file_name;
 524    }
 525
 526    // }}}
 527    // {{{ function apiVersion()
 528
 529    /**
 530     * Return the MDB2 API version
 531     *
 532     * @return  string  the MDB2 API version number
 533     *
 534     * @access  public
 535     */
 536    function apiVersion()
 537    {
 538        return '2.4.1';
 539    }
 540
 541    // }}}
 542    // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
 543
 544    /**
 545     * This method is used to communicate an error and invoke error
 546     * callbacks etc.  Basically a wrapper for PEAR::raiseError
 547     * without the message string.
 548     *
 549     * @param   mixed  int error code
 550     *
 551     * @param   int    error mode, see PEAR_Error docs
 552     *
 553     * @param   mixed  If error mode is PEAR_ERROR_TRIGGER, this is the
 554     *                 error level (E_USER_NOTICE etc).  If error mode is
 555     *                 PEAR_ERROR_CALLBACK, this is the callback function,
 556     *                 either as a function name, or as an array of an
 557     *                 object and method name.  For other error modes this
 558     *                 parameter is ignored.
 559     *
 560     * @param   string Extra debug information.  Defaults to the last
 561     *                 query and native error code.
 562     *
 563     * @return PEAR_Error instance of a PEAR Error object
 564     *
 565     * @access  private
 566     * @see     PEAR_Error
 567     */
 568    function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
 569    {
 570        $err =& PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
 571        return $err;
 572    }
 573
 574    // }}}
 575    // {{{ function isError($data, $code = null)
 576
 577    /**
 578     * Tell whether a value is a MDB2 error.
 579     *
 580     * @param   mixed   the value to test
 581     * @param   int     if is an error object, return true
 582     *                        only if $code is a string and
 583     *                        $db->getMessage() == $code or
 584     *                        $code is an integer and $db->getCode() == $code
 585     *
 586     * @return  bool    true if parameter is an error
 587     *
 588     * @access  public
 589     */
 590    function isError($data, $code = null)
 591    {
 592        if ($data instanceof MDB2_Error) {
 593            if (is_null($code)) {
 594                return true;
 595            } elseif (is_string($code)) {
 596                return $data->getMessage() === $code;
 597            } else {
 598                $code = (array)$code;
 599                return in_array($data->getCode(), $code);
 600            }
 601        }
 602        return false;
 603    }
 604
 605    // }}}
 606    // {{{ function isConnection($value)
 607
 608    /**
 609     * Tell whether a value is a MDB2 connection
 610     *
 611     * @param   mixed   value to test
 612     *
 613     * @return  bool    whether $value is a MDB2 connection
 614     *
 615     * @access  public
 616     */
 617    function isConnection($value)
 618    {
 619        return $value instanceof MDB2_Driver_Common;
 620    }
 621
 622    // }}}
 623    // {{{ function isResult($value)
 624
 625    /**
 626     * Tell whether a value is a MDB2 result
 627     *
 628     * @param   mixed   value to test
 629     *
 630     * @return  bool    whether $value is a MDB2 result
 631     *
 632     * @access  public
 633     */
 634    function isResult($value)
 635    {
 636        return $value instanceof MDB2_Result;
 637    }
 638
 639    // }}}
 640    // {{{ function isResultCommon($value)
 641
 642    /**
 643     * Tell whether a value is a MDB2 result implementing the common interface
 644     *
 645     * @param   mixed   value to test
 646     *
 647     * @return  bool    whether $value is a MDB2 result implementing the common interface
 648     *
 649     * @access  public
 650     */
 651    static function isResultCommon($value)
 652    {
 653        return $value instanceof MDB2_Result_Common;
 654    }
 655
 656    // }}}
 657    // {{{ function isStatement($value)
 658
 659    /**
 660     * Tell whether a value is a MDB2 statement interface
 661     *
 662     * @param   mixed   value to test
 663     *
 664     * @return  bool    whether $value is a MDB2 statement interface
 665     *
 666     * @access  public
 667     */
 668    function isStatement($value)
 669    {
 670        return $value instanceof MDB2_Statement;
 671    }
 672
 673    // }}}
 674    // {{{ function errorMessage($value = null)
 675
 676    /**
 677     * Return a textual error message for a MDB2 error code
 678     *
 679     * @param   int|array   integer error code,
 680                                null to get the current error code-message map,
 681                                or an array with a new error code-message map
 682     *
 683     * @return  string  error message, or false if the error code was
 684     *                  not recognized
 685     *
 686     * @access  public
 687     */
 688    function errorMessage($value = null)
 689    {
 690        static $errorMessages;
 691
 692        if (is_array($value)) {
 693            $errorMessages = $value;
 694            return MDB2_OK;
 695        }
 696
 697        if (!isset($errorMessages)) {
 698            $errorMessages = array(
 699                MDB2_OK                       => 'no error',
 700                MDB2_ERROR                    => 'unknown error',
 701                MDB2_ERROR_ALREADY_EXISTS     => 'already exists',
 702                MDB2_ERROR_CANNOT_CREATE      => 'can not create',
 703                MDB2_ERROR_CANNOT_ALTER       => 'can not alter',
 704                MDB2_ERROR_CANNOT_REPLACE     => 'can not replace',
 705                MDB2_ERROR_CANNOT_DELETE      => 'can not delete',
 706                MDB2_ERROR_CANNOT_DROP        => 'can not drop',
 707                MDB2_ERROR_CONSTRAINT         => 'constraint violation',
 708                MDB2_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
 709                MDB2_ERROR_DIVZERO            => 'division by zero',
 710                MDB2_ERROR_INVALID            => 'invalid',
 711                MDB2_ERROR_INVALID_DATE       => 'invalid date or time',
 712                MDB2_ERROR_INVALID_NUMBER     => 'invalid number',
 713                MDB2_ERROR_MISMATCH           => 'mismatch',
 714                MDB2_ERROR_NODBSELECTED       => 'no database selected',
 715                MDB2_ERROR_NOSUCHFIELD        => 'no such field',
 716                MDB2_ERROR_NOSUCHTABLE        => 'no such table',
 717                MDB2_ERROR_NOT_CAPABLE        => 'MDB2 backend not capable',
 718                MDB2_ERROR_NOT_FOUND          => 'not found',
 719                MDB2_ERROR_NOT_LOCKED         => 'not locked',
 720                MDB2_ERROR_SYNTAX             => 'syntax error',
 721                MDB2_ERROR_UNSUPPORTED        => 'not supported',
 722                MDB2_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
 723                MDB2_ERROR_INVALID_DSN        => 'invalid DSN',
 724                MDB2_ERROR_CONNECT_FAILED     => 'connect failed',
 725                MDB2_ERROR_NEED_MORE_DATA     => 'insufficient data supplied',
 726                MDB2_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
 727                MDB2_ERROR_NOSUCHDB           => 'no such database',
 728                MDB2_ERROR_ACCESS_VIOLATION   => 'insufficient permissions',
 729                MDB2_ERROR_LOADMODULE         => 'error while including on demand module',
 730                MDB2_ERROR_TRUNCATED          => 'truncated',
 731                MDB2_ERROR_DEADLOCK           => 'deadlock detected',
 732            );
 733        }
 734
 735        if (is_null($value)) {
 736            return $errorMessages;
 737        }
 738
 739        if (PEAR::isError($value)) {
 740            $value = $value->getCode();
 741        }
 742
 743        return isset($errorMessages[$value]) ?
 744           $errorMessages[$value] : $errorMessages[MDB2_ERROR];
 745    }
 746
 747    // }}}
 748    // {{{ function parseDSN($dsn)
 749
 750    /**
 751     * Parse a data source name.
 752     *
 753     * Additional keys can be added by appending a URI query string to the
 754     * end of the DSN.
 755     *
 756     * The format of the supplied DSN is in its fullest form:
 757     * <code>
 758     *  phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
 759     * </code>
 760     *
 761     * Most variations are allowed:
 762     * <code>
 763     *  phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
 764     *  phptype://username:password@hostspec/database_name
 765     *  phptype://username:password@hostspec
 766     *  phptype://username@hostspec
 767     *  phptype://hostspec/database
 768     *  phptype://hostspec
 769     *  phptype(dbsyntax)
 770     *  phptype
 771     * </code>
 772     *
 773     * @param   string  Data Source Name to be parsed
 774     *
 775     * @return  array   an associative array with the following keys:
 776     *  + phptype:  Database backend used in PHP (mysql, odbc etc.)
 777     *  + dbsyntax: Database used with regards to SQL syntax etc.
 778     *  + protocol: Communication protocol to use (tcp, unix etc.)
 779     *  + hostspec: Host specification (hostname[:port])
 780     *  + database: Database to use on the DBMS server
 781     *  + username: User name for login
 782     *  + password: Password for login
 783     *
 784     * @access  public
 785     * @author  Tomas V.V.Cox <cox@idecnet.com>
 786     */
 787    static function parseDSN($dsn)
 788    {
 789        $parsed = $GLOBALS['_MDB2_dsninfo_default'];
 790
 791        if (is_array($dsn)) {
 792            $dsn = array_merge($parsed, $dsn);
 793            if (!$dsn['dbsyntax']) {
 794                $dsn['dbsyntax'] = $dsn['phptype'];
 795            }
 796            return $dsn;
 797        }
 798
 799        // Find phptype and dbsyntax
 800        if (($pos = strpos($dsn, '://')) !== false) {
 801            $str = substr($dsn, 0, $pos);
 802            $dsn = substr($dsn, $pos + 3);
 803        } else {
 804            $str = $dsn;
 805            $dsn = null;
 806        }
 807
 808        // Get phptype and dbsyntax
 809        // $str => phptype(dbsyntax)
 810        if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
 811            $parsed['phptype']  = $arr[1];
 812            $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
 813        } else {
 814            $parsed['phptype']  = $str;
 815            $parsed['dbsyntax'] = $str;
 816        }
 817
 818        if (!count($dsn)) {
 819            return $parsed;
 820        }
 821
 822        // Get (if found): username and password
 823        // $dsn => username:password@protocol+hostspec/database
 824        if (($at = strrpos($dsn,'@')) !== false) {
 825            $str = substr($dsn, 0, $at);
 826            $dsn = substr($dsn, $at + 1);
 827            if (($pos = strpos($str, ':')) !== false) {
 828                $parsed['username'] = rawurldecode(substr($str, 0, $pos));
 829                $parsed['password'] = rawurldecode(substr($str, $pos + 1));
 830            } else {
 831                $parsed['username'] = rawurldecode($str);
 832            }
 833        }
 834
 835        // Find protocol and hostspec
 836
 837        // $dsn => proto(proto_opts)/database
 838        if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
 839            $proto       = $match[1];
 840            $proto_opts  = $match[2] ? $match[2] : false;
 841            $dsn         = $match[3];
 842
 843        // $dsn => protocol+hostspec/database (old format)
 844        } else {
 845            if (strpos($dsn, '+') !== false) {
 846                list($proto, $dsn) = explode('+', $dsn, 2);
 847            }
 848            if (   strpos($dsn, '//') === 0
 849                && strpos($dsn, '/', 2) !== false
 850                && $parsed['phptype'] == 'oci8'
 851            ) {
 852                //oracle's "Easy Connect" syntax:
 853                //"username/password@[//]host[:port][/service_name]"
 854                //e.g. "scott/tiger@//mymachine:1521/oracle"
 855                $proto_opts = $dsn;
 856                $dsn = null;
 857            } elseif (strpos($dsn, '/') !== false) {
 858                list($proto_opts, $dsn) = explode('/', $dsn, 2);
 859            } else {
 860                $proto_opts = $dsn;
 861                $dsn = null;
 862            }
 863        }
 864
 865        // process the different protocol options
 866        $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
 867        $proto_opts = rawurldecode($proto_opts);
 868        if (strpos($proto_opts, ':') !== false) {
 869            list($proto_opts, $parsed['port']) = explode(':', $proto_opts);
 870        }
 871        if ($parsed['protocol'] == 'tcp') {
 872            $parsed['hostspec'] = $proto_opts;
 873        } elseif ($parsed['protocol'] == 'unix') {
 874            $parsed['socket'] = $proto_opts;
 875        }
 876
 877        // Get dabase if any
 878        // $dsn => database
 879        if ($dsn) {
 880            // /database
 881            if (($pos = strpos($dsn, '?')) === false) {
 882                $parsed['database'] = $dsn;
 883            // /database?param1=value1&param2=value2
 884            } else {
 885                $parsed['database'] = substr($dsn, 0, $pos);
 886                $dsn = substr($dsn, $pos + 1);
 887                if (strpos($dsn, '&') !== false) {
 888                    $opts = explode('&', $dsn);
 889                } else { // database?param1=value1
 890                    $opts = array($dsn);
 891                }
 892                foreach ($opts as $opt) {
 893                    list($key, $value) = explode('=', $opt);
 894                    if (!isset($parsed[$key])) {
 895                        // don't allow params overwrite
 896                        $parsed[$key] = rawurldecode($value);
 897                    }
 898                }
 899            }
 900        }
 901
 902        return $parsed;
 903    }
 904
 905    // }}}
 906    // {{{ function fileExists($file)
 907
 908    /**
 909     * Checks if a file exists in the include path
 910     *
 911     * @param   string  filename
 912     *
 913     * @return  bool    true success and false on error
 914     *
 915     * @access  public
 916     */
 917    function fileExists($file)
 918    {
 919        // safe_mode does notwork with is_readable()
 920        if (!@ini_get('safe_mode')) {
 921             $dirs = explode(PATH_SEPARATOR, ini_get('include_path'));
 922             foreach ($dirs as $dir) {
 923                 if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) {
 924                     return true;
 925                 }
 926            }
 927        } else {
 928            $fp = @fopen($file, 'r', true);
 929            if (is_resource($fp)) {
 930                @fclose($fp);
 931                return true;
 932            }
 933        }
 934        return false;
 935    }
 936    // }}}
 937}
 938
 939// }}}
 940// {{{ class MDB2_Error extends PEAR_Error
 941
 942/**
 943 * MDB2_Error implements a class for reporting portable database error
 944 * messages.
 945 *
 946 * @package     MDB2
 947 * @category    Database
 948 * @author Stig Bakken <ssb@fast.no>
 949 */
 950class MDB2_Error extends PEAR_Error
 951{
 952    // {{{ constructor: function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null)
 953
 954    /**
 955     * MDB2_Error constructor.
 956     *
 957     * @param   mixed   MDB2 error code, or string with error message.
 958     * @param   int     what 'error mode' to operate in
 959     * @param   int     what error level to use for $mode & PEAR_ERROR_TRIGGER
 960     * @param   smixed   additional debug info, such as the last query
 961     */
 962    function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN,
 963              $level = E_USER_NOTICE, $debuginfo = null)
 964    {
 965        if (is_null($code)) {
 966            $code = MDB2_ERROR;
 967        }
 968        $this->PEAR_Error('MDB2 Error: '.MDB2::errorMessage($code), $code,
 969            $mode, $level, $debuginfo);
 970    }
 971
 972    // }}}
 973}
 974
 975// }}}
 976// {{{ class MDB2_Driver_Common extends PEAR
 977
 978/**
 979 * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
 980 *
 981 * @package     MDB2
 982 * @category    Database
 983 * @author      Lukas Smith <smith@pooteeweet.org>
 984 */
 985class MDB2_Driver_Common extends PEAR
 986{
 987    // {{{ Variables (Properties)
 988
 989    /**
 990     * index of the MDB2 object within the $GLOBALS['_MDB2_databases'] array
 991     * @var     int
 992     * @access  public
 993     */
 994    var $db_index = 0;
 995
 996    /**
 997     * DSN used for the next query
 998     * @var     array
 999     * @access  protected
1000     */
1001    var $dsn = array();
1002
1003    /**
1004     * DSN that was used to create the current connection
1005     * @var     array
1006     * @access  protected
1007     */
1008    var $connected_dsn = array();
1009
1010    /**
1011     * connection resource
1012     * @var     mixed
1013     * @access  protected
1014     */
1015    var $connection = 0;
1016
1017    /**
1018     * if the current opened connection is a persistent connection
1019     * @var     bool
1020     * @access  protected
1021     */
1022    var $opened_persistent;
1023
1024    /**
1025     * the name of the database for the next query
1026     * @var     string
1027     * @access  protected
1028     */
1029    var $database_name = '';
1030
1031    /**
1032     * the name of the database currently selected
1033     * @var     string
1034     * @access  protected
1035     */
1036    var $connected_database_name = '';
1037
1038    /**
1039     * server version information
1040     * @var     string
1041     * @access  protected
1042     */
1043    var $connected_server_info = '';
1044
1045    /**
1046     * list of all supported features of the given driver
1047     * @var     array
1048     * @access  public
1049     */
1050    var $supported = array(
1051        'sequences' => false,
1052        'indexes' => false,
1053        'affected_rows' => false,
1054        'summary_functions' => false,
1055        'order_by_text' => false,
1056        'transactions' => false,
1057        'savepoints' => false,
1058        'current_id' => false,
1059        'limit_queries' => false,
1060        'LOBs' => false,
1061        'replace' => false,
1062        'sub_selects' => false,
1063        'auto_increment' => false,
1064        'primary_key' => false,
1065        'result_introspection' => false,
1066        'prepared_statements' => false,
1067        'identifier_quoting' => false,
1068        'pattern_escaping' => false,
1069        'new_link' => false,
1070    );
1071
1072    /**
1073     * Array of supported options that can be passed to the MDB2 instance.
1074     * 
1075     * The options can be set during object creation, using
1076     * MDB2::connect(), MDB2::factory() or MDB2::singleton(). The options can 
1077     * also be set after the object is created, using MDB2::setOptions() or 
1078     * MDB2_Driver_Common::setOption().
1079     * The list of available option includes:
1080     * <ul>
1081     *  <li>$options['ssl'] -> boolean: determines if ssl should be used for connections</li>
1082     *  <li>$options['field_case'] -> CASE_LOWER|CASE_UPPER: determines what case to force on field/table names</li>
1083     *  <li>$options['disable_query'] -> boolean: determines if queries should be executed</li>
1084     *  <li>$options['result_class'] -> string: class used for result sets</li>
1085     *  <li>$options['buffered_result_class'] -> string: class used for buffered result sets</li>
1086     *  <li>$options['result_wrap_class'] -> string: class used to wrap result sets into</li>
1087     *  <li>$options['result_buffering'] -> boolean should results be buffered or not?</li>
1088     *  <li>$options['fetch_class'] -> string: class to use when fetch mode object is used</li>
1089     *  <li>$options['persistent'] -> boolean: persistent connection?</li>
1090     *  <li>$options['debug'] -> integer: numeric debug level</li>
1091     *  <li>$options['debug_handler'] -> string: function/method that captures debug messages</li>
1092     *  <li>$options['debug_expanded_output'] -> bool: BC option to determine if more context information should be send to the debug handler</li>
1093     *  <li>$options['default_text_field_length'] -> integer: default text field length to use</li>
1094     *  <li>$options['lob_buffer_length'] -> integer: LOB buffer length</li>
1095     *  <li>$options['log_line_break'] -> string: line-break format</li>
1096     *  <li>$options['idxname_format'] -> string: pattern for index name</li>
1097     *  <li>$options['seqname_format'] -> string: pattern for sequence name</li>
1098     *  <li>$options['savepoint_format'] -> string: pattern for auto generated savepoint names</li>
1099     *  <li>$options['statement_format'] -> string: pattern for prepared statement names</li>
1100     *  <li>$options['seqcol_name'] -> string: sequence column name</li>
1101     *  <li>$options['quote_identifier'] -> boolean: if identifier quoting should be done when check_option is used</li>
1102     *  <li>$options['use_transactions'] -> boolean: if transaction use should be enabled</li>
1103     *  <li>$options['decimal_places'] -> integer: number of decimal places to handle</li>
1104     *  <li>$options['portability'] -> integer: portability constant</li>
1105     *  <li>$options['modules'] -> array: short to long module name mapping for __call()</li>
1106     *  <li>$options['emulate_prepared'] -> boolean: force prepared statements to be emulated</li>
1107     *  <li>$options['datatype_map'] -> array: map user defined datatypes to other primitive datatypes</li>
1108     *  <li>$options['datatype_map_callback'] -> array: callback function/method that should be called</li>
1109     * </ul>
1110     *
1111     * @var     array
1112     * @access  public
1113     * @see     MDB2::connect()
1114     * @see     MDB2::factory()
1115     * @see     MDB2::singleton()
1116     * @see     MDB2_Driver_Common::setOption()
1117     */
1118    var $options = array(
1119        'ssl' => false,
1120        'field_case' => CASE_LOWER,
1121        'disable_query' => false,
1122        'result_class' => 'MDB2_Result_%s',
1123        'buffered_result_class' => 'MDB2_BufferedResult_%s',
1124        'result_wrap_class' => false,
1125        'result_buffering' => true,
1126        'fetch_class' => 'stdClass',
1127        'persistent' => false,
1128        'debug' => 0,
1129        'debug_handler' => 'MDB2_defaultDebugOutput',
1130        'debug_expanded_output' => false,
1131        'default_text_field_length' => 4096,
1132        'lob_buffer_length' => 8192,
1133        'log_line_break' => "\n",
1134        'idxname_format' => '%s_idx',
1135        'seqname_format' => '%s_seq',
1136        'savepoint_format' => 'MDB2_SAVEPOINT_%s',
1137        'statement_format' => 'MDB2_STATEMENT_%1$s_%2$s',
1138        'seqcol_name' => 'sequence',
1139        'quote_identifier' => false,
1140        'use_transactions' => true,
1141        'decimal_places' => 2,
1142        'portability' => MDB2_PORTABILITY_ALL,
1143        'modules' => array(
1144            'ex' => 'Extended',
1145            'dt' => 'Datatype',
1146            'mg' => 'Manager',
1147            'rv' => 'Reverse',
1148            'na' => 'Native',
1149            'fc' => 'Function',
1150        ),
1151        'emulate_prepared' => false,
1152        'datatype_map' => array(),
1153        'datatype_map_callback' => array(),
1154        'nativetype_map_callback' => array(),
1155    );
1156
1157    /**
1158     * string array
1159     * @var     string
1160     * @access  protected
1161     */
1162    var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => false, 'escape_pattern' => false);
1163
1164    /**
1165     * identifier quoting
1166     * @var     array
1167     * @access  protected
1168     */
1169    var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"');
1170
1171    /**
1172     * sql comments
1173     * @var     array
1174     * @access  protected
1175     */
1176    var $sql_comments = array(
1177        array('start' => '--', 'end' => "\n", 'escape' => false),
1178        array('start' => '/*', 'end' => '*/', 'escape' => false),
1179    );
1180
1181    /**
1182     * comparision wildcards
1183     * @var     array
1184     * @access  protected
1185     */
1186    var $wildcards = array('%', '_');
1187
1188    /**
1189     * column alias keyword
1190     * @var     string
1191     * @access  protected
1192     */
1193    var $as_keyword = ' AS ';
1194
1195    /**
1196     * warnings
1197     * @var     array
1198     * @access  protected
1199     */
1200    var $warnings = array();
1201
1202    /**
1203     * string with the debugging information
1204     * @var     string
1205     * @access  public
1206     */
1207    var $debug_output = '';
1208
1209    /**
1210     * determine if there is an open transaction
1211     * @var     bool
1212     * @access  protected
1213     */
1214    var $in_transaction = false;
1215
1216    /**
1217     * the smart transaction nesting depth
1218     * @var     int
1219     * @access  protected
1220     */
1221    var $nested_transaction_counter = null;
1222
1223    /**
1224     * the first error that occured inside a nested transaction
1225     * @var     MDB2_Error|bool
1226     * @access  protected
1227     */
1228    var $has_transaction_error = false;
1229
1230    /**
1231     * result offset used in the next query
1232     * @var     int
1233     * @access  protected
1234     */
1235    var $offset = 0;
1236
1237    /**
1238     * result limit used in the next query
1239     * @var     int
1240     * @access  protected
1241     */
1242    var $limit = 0;
1243
1244    /**
1245     * Database backend used in PHP (mysql, odbc etc.)
1246     * @var     string
1247     * @access  public
1248     */
1249    var $phptype;
1250
1251    /**
1252     * Database used with regards to SQL syntax etc.
1253     * @var     string
1254     * @access  public
1255     */
1256    var $dbsyntax;
1257
1258    /**
1259     * the last query sent to the driver
1260     * @var     string
1261     * @access  public
1262     */
1263    var $last_query;
1264
1265    /**
1266     * the default fetchmode used
1267     * @var     int
1268     * @access  protected
1269     */
1270    var $fetchmode = MDB2_FETCHMODE_ORDERED;
1271
1272    /**
1273     * array of module instances
1274     * @var     array
1275     * @access  protected
1276     */
1277    var $modules = array();
1278
1279    /**
1280     * determines of the PHP4 destructor emulation has been enabled yet
1281     * @var     array
1282     * @access  protected
1283     */
1284    var $destructor_registered = true;
1285
1286    // }}}
1287    // {{{ constructor: function __construct()
1288
1289    /**
1290     * Constructor
1291     */
1292    function __construct()
1293    {
1294        end($GLOBALS['_MDB2_databases']);
1295        $db_index = key($GLOBALS['_MDB2_databases']) + 1;
1296        $GLOBALS['_MDB2_databases'][$db_index] = &$this;
1297        $this->db_index = $db_index;
1298    }
1299
1300    // }}}
1301    // {{{ destructor: function __destruct()
1302
1303    /**
1304     *  Destructor
1305     */
1306    function __destruct()
1307    {
1308        $this->disconnect(false);
1309    }
1310
1311    // }}}
1312    // {{{ function free()
1313
1314    /**
1315     * Free the internal references so that the instance can be destroyed
1316     *
1317     * @return  bool    true on success, false if result is invalid
1318     *
1319     * @access  public
1320     */
1321    function free()
1322    {
1323        unset($GLOBALS['_MDB2_databases'][$this->db_index]);
1324        unset($this->db_index);
1325        return MDB2_OK;
1326    }
1327
1328    // }}}
1329    // {{{ function __toString()
1330
1331    /**
1332     * String conversation
1333     *
1334     * @return  string representation of the object
1335     *
1336     * @access  public
1337     */
1338    function __toString()
1339    {
1340        $info = get_class($this);
1341        $info.= ': (phptype = '.$this->phptype.', dbsyntax = '.$this->dbsyntax.')';
1342        if ($this->connection) {
1343            $info.= ' [connected]';
1344        }
1345        return $info;
1346    }
1347
1348    // }}}
1349    // {{{ function errorInfo($error = null)
1350
1351    /**
1352     * This method is used to collect information about an error
1353     *
1354     * @param   mixed   error code or resource
1355     *
1356     * @return  array   with MDB2 errorcode, native error code, native message
1357     *
1358     * @access  public
1359     */
1360    function errorInfo($error = null)
1361    {
1362        return array($error, null, null);
1363    }
1364
1365    // }}}
1366    // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
1367
1368    /**
1369     * This method is used to communicate an error and invoke error
1370     * callbacks etc.  Basically a wrapper for PEAR::raiseError
1371     * without the message string.
1372     *
1373     * @param   mixed   integer error code, or a PEAR error object (all other
1374     *                  parameters are ignored if this parameter is an object
1375     * @param   int     error mode, see PEAR_Error docs
1376     * @param   mixed   If error mode is PEAR_ERROR_TRIGGER, this is the
1377         *              error level (E_USER_NOTICE etc).  If error mode is
1378     *                  PEAR_ERROR_CALLBACK, this is the callback function,
1379     *                  either as a function name, or as an array of an
1380     *                  object and method name.  For other error modes this
1381     *                  parameter is ignored.
1382     * @param   string  Extra debug information.  Defaults to the last
1383     *                  query and native error code.
1384     * @param   string  name of the method that triggered the error
1385     *
1386     * @return PEAR_Error   instance of a PEAR Error object
1387     *
1388     * @access  public
1389     * @see     PEAR_Error
1390     */
1391    function &raiseError($code = null, $mode = null, $options = null, $userinfo = null, $method = null)
1392    {
1393        $userinfo = "[Error message: $userinfo]\n";
1394        // The error is yet a MDB2 error object
1395        if (PEAR::isError($code)) {
1396            // because we use the static PEAR::raiseError, our global
1397            // handler should be used if it is set
1398            if (is_null($mode) && !empty($this->_default_error_mode)) {
1399                $mode    = $this->_default_error_mode;
1400                $options = $this->_default_error_options;
1401            }
1402            if (is_null($userinfo)) {
1403                $userinfo = $code->getUserinfo();
1404            }
1405            $code = $code->getCode();
1406        } elseif ($code == MDB2_ERROR_NOT_FOUND) {
1407            // extension not loaded: don't call $this->errorInfo() or the script
1408            // will die
1409        } elseif (isset($this->connection)) {
1410            if (!empty($this->last_query)) {
1411                $userinfo.= "[Last executed query: {$this->last_query}]\n";
1412            }
1413            $native_errno = $native_msg = null;
1414            list($code, $native_errno, $native_msg) = $this->errorInfo($code);
1415            if (!is_null($native_errno) && $native_errno !== '') {
1416                $userinfo.= "[Native code: $native_errno]\n";
1417            }
1418            if (!is_null($native_msg) && $native_msg !== '') {
1419                $userinfo.= "[Native message: ". strip_tags($native_msg) ."]\n";
1420            }
1421            if (!is_null($method)) {
1422                $userinfo = $method.': '.$userinfo;
1423            }
1424        }
1425
1426        $err =& PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
1427        if ($err->getMode() !== PEAR_ERROR_RETURN
1428            && isset($this->nested_transaction_counter) && !$this->has_transaction_error) {
1429            $this->has_transaction_error =& $err;
1430        }
1431        return $err;
1432    }
1433
1434    // }}}
1435    // {{{ function resetWarnings()
1436
1437    /**
1438     * reset the warning array
1439     *
1440     * @return void
1441     *
1442     * @access  public
1443     */
1444    function resetWarnings()
1445    {
1446        $this->warnings = array();
1447    }
1448
1449    // }}}
1450    // {{{ function getWarnings()
1451
1452    /**
1453     * Get all warnings in reverse order.
1454     * This means that the last warning is the first element in the array
1455     *
1456     * @return  array   with warnings
1457     *
1458     * @access  public
1459     * @see     resetWarnings()
1460     */
1461    function getWarnings()
1462    {
1463        return array_reverse($this->warnings);
1464    }
1465
1466    // }}}
1467    // {{{ function setFetchMode($fetchmode, $object_class = 'stdClass')
1468
1469    /**
1470     * Sets which fetch mode should be used by default on queries
1471     * on this connection
1472     *
1473     * @param   int     MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC
1474     *                               or MDB2_FETCHMODE_OBJECT
1475     * @param   string  the class name of the object to be returned
1476     *                               by the fetch methods when the
1477     *                               MDB2_FETCHMODE_OBJECT mode is selected.
1478     *                               If no class is specified by default a cast
1479     *                               to object from the assoc array row will be
1480     *                               done.  There is also the possibility to use
1481     *                               and extend the 'MDB2_row' class.
1482     *
1483     * @return  mixed   MDB2_OK or MDB2 Error Object
1484     *
1485     * @access  public
1486     * @see     MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC, MDB2_FETCHMODE_OBJECT
1487     */
1488    function setFetchMode($fetchmode, $object_class = 'stdClass')
1489    {
1490        switch ($fetchmode) {
1491        case MDB2_FETCHMODE_OBJECT:
1492            $this->options['fetch_class'] = $object_class;
1493        case MDB2_FETCHMODE_ORDERED:
1494        case MDB2_FETCHMODE_ASSOC:
1495            $this->fetchmode = $fetchmode;
1496            break;
1497        default:
1498            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
1499                'invalid fetchmode mode', __FUNCTION__);
1500        }
1501
1502        return MDB2_OK;
1503    }
1504
1505    // }}}
1506    // {{{ fu…

Large files files are truncated, but you can click here to view the full file