[ Index ]
 

Code source de PHPonTrax 2.6.6-svn

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/test/mockDB/ -> DB.php (source)

   1  <?php
   2  /**
   3   *  File for mock DB class
   4   *
   5   *  This file has the same name as the file holding the {@link
   6   *  http://pear.php.net/package/DB PEAR DB class}.
   7   *  To use the mock DB, put this file in the PHP include path ahead of
   8   *  the PEAR library, so that any class which requires DB.php will
   9   *  load this version.
  10   *
  11   * (PHP 5)
  12   *
  13   * @package PHPonTraxTest
  14   * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  15   * @copyright (c) Walter O. Haas 2006
  16   * @version $Id: DB.php 198 2006-04-20 16:20:30Z haas $
  17   * @author Walt Haas <haas@xmission.com>
  18   */
  19  
  20  require_once 'PEAR.php';
  21  require_once 'PHPUnit2/Framework/Assert.php';
  22  
  23  /**
  24   * The code returned by many methods upon success
  25   */
  26  define('DB_OK', 1);
  27  
  28  /**
  29   * Unkown error
  30   */
  31  define('DB_ERROR', -1);
  32  
  33  /**
  34   * Syntax error
  35   */
  36  define('DB_ERROR_SYNTAX', -2);
  37  
  38  /**
  39   * Tried to insert a duplicate value into a primary or unique index
  40   */
  41  define('DB_ERROR_CONSTRAINT', -3);
  42  
  43  /**
  44   * An identifier in the query refers to a non-existant object
  45   */
  46  define('DB_ERROR_NOT_FOUND', -4);
  47  
  48  /**
  49   * Tried to create a duplicate object
  50   */
  51  define('DB_ERROR_ALREADY_EXISTS', -5);
  52  
  53  /**
  54   * The current driver does not support the action you attempted
  55   */
  56  define('DB_ERROR_UNSUPPORTED', -6);
  57  
  58  /**
  59   * The number of parameters does not match the number of placeholders
  60   */
  61  define('DB_ERROR_MISMATCH', -7);
  62  
  63  /**
  64   * A literal submitted did not match the data type expected
  65   */
  66  define('DB_ERROR_INVALID', -8);
  67  
  68  /**
  69   * The current DBMS does not support the action you attempted
  70   */
  71  define('DB_ERROR_NOT_CAPABLE', -9);
  72  
  73  /**
  74   * A literal submitted was too long so the end of it was removed
  75   */
  76  define('DB_ERROR_TRUNCATED', -10);
  77  
  78  /**
  79   * A literal number submitted did not match the data type expected
  80   */
  81  define('DB_ERROR_INVALID_NUMBER', -11);
  82  
  83  /**
  84   * A literal date submitted did not match the data type expected
  85   */
  86  define('DB_ERROR_INVALID_DATE', -12);
  87  
  88  /**
  89   * Attempt to divide something by zero
  90   */
  91  define('DB_ERROR_DIVZERO', -13);
  92  
  93  /**
  94   * A database needs to be selected
  95   */
  96  define('DB_ERROR_NODBSELECTED', -14);
  97  
  98  /**
  99   * Could not create the object requested
 100   */
 101  define('DB_ERROR_CANNOT_CREATE', -15);
 102  
 103  /**
 104   * Could not drop the database requested because it does not exist
 105   */
 106  define('DB_ERROR_CANNOT_DROP', -17);
 107  
 108  /**
 109   * An identifier in the query refers to a non-existant table
 110   */
 111  define('DB_ERROR_NOSUCHTABLE', -18);
 112  
 113  /**
 114   * An identifier in the query refers to a non-existant column
 115   */
 116  define('DB_ERROR_NOSUCHFIELD', -19);
 117  
 118  /**
 119   * The data submitted to the method was inappropriate
 120   */
 121  define('DB_ERROR_NEED_MORE_DATA', -20);
 122  
 123  /**
 124   * The attempt to lock the table failed
 125   */
 126  define('DB_ERROR_NOT_LOCKED', -21);
 127  
 128  /**
 129   * The number of columns doesn't match the number of values
 130   */
 131  define('DB_ERROR_VALUE_COUNT_ON_ROW', -22);
 132  
 133  /**
 134   * The DSN submitted has problems
 135   */
 136  define('DB_ERROR_INVALID_DSN', -23);
 137  
 138  /**
 139   * Could not connect to the database
 140   */
 141  define('DB_ERROR_CONNECT_FAILED', -24);
 142  
 143  /**
 144   * The PHP extension needed for this DBMS could not be found
 145   */
 146  define('DB_ERROR_EXTENSION_NOT_FOUND',-25);
 147  
 148  /**
 149   * The present user has inadequate permissions to perform the task requestd
 150   */
 151  define('DB_ERROR_ACCESS_VIOLATION', -26);
 152  
 153  /**
 154   * The database requested does not exist
 155   */
 156  define('DB_ERROR_NOSUCHDB', -27);
 157  
 158  /**
 159   * Tried to insert a null value into a column that doesn't allow nulls
 160   */
 161  define('DB_ERROR_CONSTRAINT_NOT_NULL',-29);
 162  
 163  /**
 164   * Identifiers for the placeholders used in prepared statements.
 165   * @see prepare()
 166   */
 167  
 168  /**
 169   * Indicates a scalar (<kbd>?</kbd>) placeholder was used
 170   *
 171   * Quote and escape the value as necessary.
 172   */
 173  define('DB_PARAM_SCALAR', 1);
 174  
 175  /**
 176   * Indicates an opaque (<kbd>&</kbd>) placeholder was used
 177   *
 178   * The value presented is a file name.  Extract the contents of that file
 179   * and place them in this column.
 180   */
 181  define('DB_PARAM_OPAQUE', 2);
 182  
 183  /**
 184   * Indicates a misc (<kbd>!</kbd>) placeholder was used
 185   *
 186   * The value should not be quoted or escaped.
 187   */
 188  define('DB_PARAM_MISC',   3);
 189  
 190  /**
 191   * The different ways of returning binary data from queries.
 192   */
 193  
 194  /**
 195   * Sends the fetched data straight through to output
 196   */
 197  define('DB_BINMODE_PASSTHRU', 1);
 198  
 199  /**
 200   * Lets you return data as usual
 201   */
 202  define('DB_BINMODE_RETURN', 2);
 203  
 204  /**
 205   * Converts the data to hex format before returning it
 206   *
 207   * For example the string "123" would become "313233".
 208   */
 209  define('DB_BINMODE_CONVERT', 3);
 210  
 211  /**
 212   * Fetchmode constants
 213   */
 214  define('DB_FETCHMODE_DEFAULT', 0);
 215  define('DB_FETCHMODE_ORDERED', 1);
 216  define('DB_FETCHMODE_ASSOC', 2);
 217  define('DB_FETCHMODE_OBJECT', 3);
 218  
 219  /**
 220   * For multi-dimensional results, make the column name the first level
 221   * of the array and put the row number in the second level of the array
 222   *
 223   * This is flipped from the normal behavior, which puts the row numbers
 224   * in the first level of the array and the column names in the second level.
 225   */
 226  define('DB_FETCHMODE_FLIPPED', 4);
 227  
 228  /**
 229   * Old fetch modes.  Left here for compatibility.
 230   */
 231  define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
 232  define('DB_GETMODE_ASSOC',   DB_FETCHMODE_ASSOC);
 233  define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED);
 234  
 235  /**
 236   * The type of information to return from the tableInfo() method.
 237   *
 238   * Bitwised constants, so they can be combined using <kbd>|</kbd>
 239   * and removed using <kbd>^</kbd>.
 240   *
 241   * @see tableInfo()
 242   */
 243  define('DB_TABLEINFO_ORDER', 1);
 244  define('DB_TABLEINFO_ORDERTABLE', 2);
 245  define('DB_TABLEINFO_FULL', 3);
 246  
 247  /**
 248   * The type of query to create with the automatic query building methods.
 249   * @see autoPrepare(), autoExecute()
 250   */
 251  define('DB_AUTOQUERY_INSERT', 1);
 252  define('DB_AUTOQUERY_UPDATE', 2);
 253  
 254  /**
 255   * Portability Modes.
 256   *
 257   * Bitwised constants, so they can be combined using <kbd>|</kbd>
 258   * and removed using <kbd>^</kbd>.
 259   *
 260   * @see setOption()
 261   */
 262  
 263  /**
 264   * Turn off all portability features
 265   */
 266  define('DB_PORTABILITY_NONE', 0);
 267  
 268  /**
 269   * Convert names of tables and fields to lower case
 270   * when using the get*(), fetch*() and tableInfo() methods
 271   */
 272  define('DB_PORTABILITY_LOWERCASE', 1);
 273  
 274  /**
 275   * Right trim the data output by get*() and fetch*()
 276   */
 277  define('DB_PORTABILITY_RTRIM', 2);
 278  
 279  /**
 280   * Force reporting the number of rows deleted
 281   */
 282  define('DB_PORTABILITY_DELETE_COUNT', 4);
 283  
 284  /**
 285   * Enable hack that makes numRows() work in Oracle
 286   */
 287  define('DB_PORTABILITY_NUMROWS', 8);
 288  
 289  /**
 290   * Makes certain error messages in certain drivers compatible
 291   * with those from other DBMS's
 292   *
 293   * + mysql, mysqli:  change unique/primary key constraints
 294   *   DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT
 295   *
 296   * + odbc(access):  MS's ODBC driver reports 'no such field' as code
 297   *   07001, which means 'too few parameters.'  When this option is on
 298   *   that code gets mapped to DB_ERROR_NOSUCHFIELD.
 299   */
 300  define('DB_PORTABILITY_ERRORS', 16);
 301  
 302  /**
 303   * Convert null values to empty strings in data output by
 304   * get*() and fetch*()
 305   */
 306  define('DB_PORTABILITY_NULL_TO_EMPTY', 32);
 307  
 308  /**
 309   * Turn on all portability features
 310   */
 311  define('DB_PORTABILITY_ALL', 63);
 312  
 313  /**
 314   *  Mock DB class for testing
 315   *
 316   *  This class is a mock version of the
 317   *  {@link http://pear.php.net/package/DB PEAR DB class}.  It is
 318   *  intended to provide the same interface as the real DB class, plus
 319   *  a small database sufficient to test software.
 320   */
 321  
 322  class DB {
 323  
 324      /**
 325       * Create a new DB object for the specified database type but don't
 326       * connect to the database
 327       *
 328       * @param string $type     the database type (eg "mysql")
 329       * @param array  $options  an associative array of option names and values
 330       * @return object  a new DB object.  A DB_Error object on failure.
 331       * @see DB_common::setOption()
 332       *  @todo Implement mock DB::factory
 333       */
 334      public function &factory($type, $options = false)
 335      {
 336  //        if (!is_array($options)) {
 337  //            $options = array('persistent' => $options);
 338  //        }
 339  //
 340  //        if (isset($options['debug']) && $options['debug'] >= 2) {
 341  //            // expose php errors with sufficient debug level
 342  //            include_once "DB/{$type}.php";
 343  //        } else {
 344  //            @include_once "DB/{$type}.php";
 345  //        }
 346  //
 347  //        $classname = "DB_${type}";
 348  //
 349  //        if (!class_exists($classname)) {
 350  //            $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
 351  //                                    "Unable to include the DB/{$type}.php"
 352  //                                    . " file for '$dsn'",
 353  //                                    'DB_Error', true);
 354  //            return $tmp;
 355  //        }
 356  //
 357  //        @$obj =& new $classname;
 358  //
 359  //        foreach ($options as $option => $value) {
 360  //            $test = $obj->setOption($option, $value);
 361  //            if (DB::isError($test)) {
 362  //                return $test;
 363  //            }
 364  //        }
 365  //
 366  //        return $obj;
 367      }
 368  
 369      /**
 370       * Create a new DB object including a connection to the specified database
 371       *
 372       * @param mixed $dsn      the string "data source name" or array in the
 373       *                         format returned by DB::parseDSN()
 374       * @param array $options  an associative array of option names and values
 375       * @return object  a new DB object.  A DB_Error object on failure.
 376       * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError()
 377       *  @todo Implement mock DB::connect
 378       */
 379      function &connect($dsn, $options = array())
 380      {
 381          $dsninfo = DB::parseDSN($dsn);
 382          $type = $dsninfo['phptype'];
 383  
 384          // only support MySQL at the moment
 385          PHPUnit2_Framework_Assert::assertEquals($type,'mysql');
 386          @$obj =& new DB_mysql;
 387  
 388          foreach ($options as $option => $value) {
 389              $test = $obj->setOption($option, $value);
 390              if (DB::isError($test)) {
 391                  return $test;
 392              }
 393          }
 394  
 395  //        $err = $obj->connect($dsninfo, $obj->getOption('persistent'));
 396  //        if (DB::isError($err)) {
 397  //            $err->addUserInfo($dsn);
 398  //            return $err;
 399  //        }
 400  //
 401          return $obj;
 402      }
 403  
 404      /**
 405       * Return the DB API version
 406       *
 407       * @return string  the DB API version number
 408       */
 409      function apiVersion()
 410      {
 411          return '1.7.6';
 412      }
 413  
 414      /**
 415       * Determines if a variable is a DB_Error object
 416       *
 417       * @param mixed $value  the variable to check
 418       * @return bool  whether $value is DB_Error object
 419       */
 420      function isError($value)
 421      {
 422          return is_a($value, 'DB_Error');
 423      }
 424  
 425      /**
 426       * Determines if a value is a DB_<driver> object
 427       *
 428       * @param mixed $value  the value to test
 429       * @return bool  whether $value is a DB_<driver> object
 430       *  @todo Implement mock DB::isConnection
 431       */
 432      function isConnection($value)
 433      {
 434  //        return (is_object($value) &&
 435  //                is_subclass_of($value, 'db_common') &&
 436  //                method_exists($value, 'simpleQuery'));
 437      }
 438  
 439      /**
 440       * Tell whether a query is a data manipulation or data definition query
 441       *
 442       * @param string $query  the query
 443       * @return boolean  whether $query is a data manipulation query
 444       */
 445      function isManip($query)
 446      {
 447          $manips = 'INSERT|UPDATE|DELETE|REPLACE|'
 448                  . 'CREATE|DROP|'
 449                  . 'LOAD DATA|SELECT .* INTO|COPY|'
 450                  . 'ALTER|GRANT|REVOKE|'
 451                  . 'LOCK|UNLOCK';
 452          if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) {
 453              return true;
 454          }
 455          return false;
 456      }
 457  
 458      /**
 459       * Return a textual error message for a DB error code
 460       *
 461       * @param integer $value  the DB error code
 462       * @return string  the error message or false if the error code was
 463       *                  not recognized
 464       *  @todo Implement mock DB::errorMessage
 465       */
 466      public function errorMessage($value)
 467      {
 468          static $errorMessages;
 469          if (!isset($errorMessages)) {
 470              $errorMessages = array(
 471                  DB_ERROR                    => 'unknown error',
 472                  DB_ERROR_ACCESS_VIOLATION   => 'insufficient permissions',
 473                  DB_ERROR_ALREADY_EXISTS     => 'already exists',
 474                  DB_ERROR_CANNOT_CREATE      => 'can not create',
 475                  DB_ERROR_CANNOT_DROP        => 'can not drop',
 476                  DB_ERROR_CONNECT_FAILED     => 'connect failed',
 477                  DB_ERROR_CONSTRAINT         => 'constraint violation',
 478                  DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
 479                  DB_ERROR_DIVZERO            => 'division by zero',
 480                  DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
 481                  DB_ERROR_INVALID            => 'invalid',
 482                  DB_ERROR_INVALID_DATE       => 'invalid date or time',
 483                  DB_ERROR_INVALID_DSN        => 'invalid DSN',
 484                  DB_ERROR_INVALID_NUMBER     => 'invalid number',
 485                  DB_ERROR_MISMATCH           => 'mismatch',
 486                  DB_ERROR_NEED_MORE_DATA     => 'insufficient data supplied',
 487                  DB_ERROR_NODBSELECTED       => 'no database selected',
 488                  DB_ERROR_NOSUCHDB           => 'no such database',
 489                  DB_ERROR_NOSUCHFIELD        => 'no such field',
 490                  DB_ERROR_NOSUCHTABLE        => 'no such table',
 491                  DB_ERROR_NOT_CAPABLE        => 'DB backend not capable',
 492                  DB_ERROR_NOT_FOUND          => 'not found',
 493                  DB_ERROR_NOT_LOCKED         => 'not locked',
 494                  DB_ERROR_SYNTAX             => 'syntax error',
 495                  DB_ERROR_UNSUPPORTED        => 'not supported',
 496                  DB_ERROR_TRUNCATED          => 'truncated',
 497                  DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
 498                  DB_OK                       => 'no error',
 499              );
 500          }
 501  
 502  //        if (DB::isError($value)) {
 503  //            $value = $value->getCode();
 504  //        }
 505  //
 506  //        return isset($errorMessages[$value]) ? $errorMessages[$value]
 507  //                     : $errorMessages[DB_ERROR];
 508      }
 509  
 510      /**
 511       * Parse a data source name
 512       *
 513       * @param string $dsn Data Source Name to be parsed
 514       * @return array an associative array with the following keys:
 515       *  + phptype:  Database backend used in PHP (mysql, odbc etc.)
 516       *  + dbsyntax: Database used with regards to SQL syntax etc.
 517       *  + protocol: Communication protocol to use (tcp, unix etc.)
 518       *  + hostspec: Host specification (hostname[:port])
 519       *  + database: Database to use on the DBMS server
 520       *  + username: User name for login
 521       *  + password: Password for login
 522       *  @todo Implement mock DB::parseDSN
 523       */
 524      public function parseDSN($dsn)
 525      {
 526          $parsed = array(
 527              'phptype'  => false,
 528              'dbsyntax' => false,
 529              'username' => false,
 530              'password' => false,
 531              'protocol' => false,
 532              'hostspec' => false,
 533              'port'     => false,
 534              'socket'   => false,
 535              'database' => false,
 536          );
 537  
 538          if (is_array($dsn)) {
 539              $dsn = array_merge($parsed, $dsn);
 540              if (!$dsn['dbsyntax']) {
 541                  $dsn['dbsyntax'] = $dsn['phptype'];
 542              }
 543              return $dsn;
 544          }
 545  
 546          // Find phptype and dbsyntax
 547          if (($pos = strpos($dsn, '://')) !== false) {
 548              $str = substr($dsn, 0, $pos);
 549              $dsn = substr($dsn, $pos + 3);
 550          } else {
 551              $str = $dsn;
 552              $dsn = null;
 553          }
 554  
 555          // Get phptype and dbsyntax
 556          // $str => phptype(dbsyntax)
 557          if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
 558              $parsed['phptype']  = $arr[1];
 559              $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
 560          } else {
 561              $parsed['phptype']  = $str;
 562              $parsed['dbsyntax'] = $str;
 563          }
 564  
 565          if (!count($dsn)) {
 566              return $parsed;
 567          }
 568  
 569          // Get (if found): username and password
 570          // $dsn => username:password@protocol+hostspec/database
 571          if (($at = strrpos($dsn,'@')) !== false) {
 572              $str = substr($dsn, 0, $at);
 573              $dsn = substr($dsn, $at + 1);
 574              if (($pos = strpos($str, ':')) !== false) {
 575                  $parsed['username'] = rawurldecode(substr($str, 0, $pos));
 576                  $parsed['password'] = rawurldecode(substr($str, $pos + 1));
 577              } else {
 578                  $parsed['username'] = rawurldecode($str);
 579              }
 580          }
 581  
 582          // Find protocol and hostspec
 583  
 584          if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
 585              // $dsn => proto(proto_opts)/database
 586              $proto       = $match[1];
 587              $proto_opts  = $match[2] ? $match[2] : false;
 588              $dsn         = $match[3];
 589  
 590          } else {
 591              // $dsn => protocol+hostspec/database (old format)
 592              if (strpos($dsn, '+') !== false) {
 593                  list($proto, $dsn) = explode('+', $dsn, 2);
 594              }
 595              if (strpos($dsn, '/') !== false) {
 596                  list($proto_opts, $dsn) = explode('/', $dsn, 2);
 597              } else {
 598                  $proto_opts = $dsn;
 599                  $dsn = null;
 600              }
 601          }
 602  
 603          // process the different protocol options
 604          $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
 605          $proto_opts = rawurldecode($proto_opts);
 606          if ($parsed['protocol'] == 'tcp') {
 607              if (strpos($proto_opts, ':') !== false) {
 608                  list($parsed['hostspec'],
 609                       $parsed['port']) = explode(':', $proto_opts);
 610              } else {
 611                  $parsed['hostspec'] = $proto_opts;
 612              }
 613          } elseif ($parsed['protocol'] == 'unix') {
 614              $parsed['socket'] = $proto_opts;
 615          }
 616  
 617          // Get dabase if any
 618          // $dsn => database
 619          if ($dsn) {
 620              if (($pos = strpos($dsn, '?')) === false) {
 621                  // /database
 622                  $parsed['database'] = rawurldecode($dsn);
 623              } else {
 624                  // /database?param1=value1&param2=value2
 625                  $parsed['database'] = rawurldecode(substr($dsn, 0, $pos));
 626                  $dsn = substr($dsn, $pos + 1);
 627                  if (strpos($dsn, '&') !== false) {
 628                      $opts = explode('&', $dsn);
 629                  } else { // database?param1=value1
 630                      $opts = array($dsn);
 631                  }
 632                  foreach ($opts as $opt) {
 633                      list($key, $value) = explode('=', $opt);
 634                      if (!isset($parsed[$key])) {
 635                          // don't allow params overwrite
 636                          $parsed[$key] = rawurldecode($value);
 637                      }
 638                  }
 639              }
 640          }
 641  
 642          return $parsed;
 643      }
 644  }
 645  
 646  /**
 647   *  Mock DB_common for testing
 648   *  @todo Implement mock DB_common class
 649   */
 650  class DB_common extends PEAR {
 651  
 652      /**
 653       *  Mock Database
 654       */
 655      protected static $database =
 656          //  Person names table
 657          array('person_names' =>
 658                //  Description
 659                array('info' =>
 660                      array(array('table' => 'person_names',
 661                                  'name'  => 'id',
 662                                  'type'  => 'int',
 663                                  'len'   => '11',
 664                                  'flags' => 'primary_key not_null'),
 665                            array('table' => 'person_names',
 666                                  'name'  => 'prefix',
 667                                  'type'  => 'string',
 668                                  'len'   => '20',
 669                                  'flags' => ''),
 670                            array('table' => 'person_names',
 671                                  'name'  => 'first_name',
 672                                  'type'  => 'string',
 673                                  'len'   => '40',
 674                                  'flags' => ''),
 675                            array('table' => 'person_names',
 676                                  'name'  => 'mi',
 677                                  'type'  => 'string',
 678                                  'len'   => '1',
 679                                  'flags' => ''),
 680                            array('table' => 'person_names',
 681                                  'name'  => 'last_name',
 682                                  'type'  => 'string',
 683                                  'len'   => '40',
 684                                  'flags' => ''),
 685                            array('table' => 'person_names',
 686                                  'name'  => 'suffix',
 687                                  'type'  => 'string',
 688                                  'len'   => '20',
 689                                  'flags' => ''),
 690                            ),
 691                      'data' =>
 692                      array()
 693                      ),
 694  
 695                //  Data types table
 696                'data_types' =>
 697  
 698                //  Description
 699                array('info' =>
 700                      array(array("table" => "data_types",
 701                                  "name"  => "id",
 702                                  "type"  => "int",
 703                                  "len"   => '11',
 704                                  "flags" => "not_null primary_key auto_increment"),
 705                            array("table" => "data_types",
 706                                  "name"  => "bit_type",
 707                                  "type"  => "int",
 708                                  "len"   => '1',
 709                                  "flags" => ""),
 710                            array("table" => "data_types",
 711                                  "name"  => "tinyint_type",
 712                                  "type"  => "int",
 713                                  "len"   =>  '4',
 714                                  "flags" =>  ""),
 715                            array("table" =>  "data_types",
 716                                  "name"  =>  "bool_type",
 717                                  "type"  =>  "int",
 718                                  "len"   =>  '1',
 719                                  "flags" =>  ""),
 720                            array("table" =>  "data_types",
 721                                  "name"  =>  "boolean_type",
 722                                  "type"  =>  "int",
 723                                  "len"   =>  '1',
 724                                  "flags" =>  ""),
 725                            array("table" =>  "data_types",
 726                                  "name"  =>  "smallint_type",
 727                                  "type"  =>  "int",
 728                                  "len"   =>  '6',
 729                                  "flags" =>  ""),
 730                            array("table" =>  "data_types",
 731                                  "name"  =>  "mediumint_type",
 732                                  "type"  =>  "int",
 733                                  "len"   =>  '9',
 734                                  "flags" =>  ""),
 735                            array("table"   =>  "data_types",
 736                                  "name"    =>  "int_type",
 737                                  "type"    =>  "int",
 738                                  "len"     =>  '11',
 739                                  "flags"   =>  ""),
 740                            array("table" =>  "data_types",
 741                                  "name"  =>  "integer_type",
 742                                  "type"  =>  "int",
 743                                  "len"   =>  '11',
 744                                  "flags" =>  ""),
 745                            array("table" =>  "data_types",
 746                                  "name"  =>  "bigint_type",
 747                                  "type"  =>  "int",
 748                                  "len"   =>  '20',
 749                                  "flags" =>  ""),
 750                            array("table" =>  "data_types",
 751                                  "name"  =>  "float_type",
 752                                  "type"  =>  "real",
 753                                  "len"   =>  '12',
 754                                  "flags" =>  ""),
 755                            array("table" =>  "data_types",
 756                                  "name"  =>  "double_type",
 757                                  "type"  =>  "real",
 758                                  "len"   =>  '22',
 759                                  "flags" =>  ""),
 760                            array("table" =>  "data_types",
 761                                  "name"  =>  "double_precision_type",
 762                                  "type"  =>  "real",
 763                                  "len"   =>  '22',
 764                                  "flags" =>  ""),
 765                            array("table" =>  "data_types",
 766                                  "name"  =>  "decimal_type",
 767                                  "type"  =>  "real",
 768                                  "len"   =>  '11',
 769                                  "flags" =>  ""),
 770                            array("table" =>  "data_types",
 771                                  "name"  =>  "dec_type",
 772                                  "type"  =>  "real",
 773                                  "len"   =>  '11',
 774                                  "flags" =>  ""),
 775                            array("table" => "data_types",
 776                                  "name"  => "numeric_type",
 777                                  "type"  => "real",
 778                                  "len"   => '11',
 779                                  "flags" => ""),
 780                            array("table" => "data_types",
 781                                  "name"  => "fixed_type",
 782                                  "type"  => "real",
 783                                  "len"   => '11',
 784                                  "flags" => ""),
 785                            array("table" => "data_types",
 786                                  "name"  => "date_type",
 787                                  "type"  => "date",
 788                                  "len"   => '10',
 789                                  "flags" => "binary"),
 790                            array("table" => "data_types",
 791                                  "name"  => "datetime_type",
 792                                  "type"  => "datetime",
 793                                  "len"   => '19',
 794                                  "flags" => "binary"),
 795                            array("table" => "data_types",
 796                                  "name"  => "timestamp_type",
 797                                  "type"  => "timestamp",
 798                                  "len"   => '19',
 799                                  "flags" => "unsigned zerofill binary"),
 800                            array("table" => "data_types",
 801                                  "name"  => "time_type",
 802                                  "type"  => "time",
 803                                  "len"   => '8',
 804                                  "flags" => "binary"),
 805                            array("table" => "data_types",
 806                                  "name"  => "year_type",
 807                                  "type"  => "year",
 808                                  "len"   => '4',
 809                                  "flags" => "unsigned zerofill"),
 810                            array("table" => "data_types",
 811                                  "name"  => "char_type",
 812                                  "type"  => "string",
 813                                  "len"   => '20',
 814                                  "flags" => ""),
 815                            array("table" => "data_types",
 816                                  "name"  => "varchar_type",
 817                                  "type"  => "string",
 818                                  "len"   => '20',
 819                                  "flags" => ""),
 820                            array("table" => "data_types",
 821                                  "name"  => "nchar_type",
 822                                  "type"  => "string",
 823                                  "len"   => '20',
 824                                  "flags" => ""),
 825                            array("table" => "data_types",
 826                                  "name"  => "binary_type",
 827                                  "type"  => "string",
 828                                  "len"   => '20',
 829                                  "flags" => "binary"),
 830                            array("table" => "data_types",
 831                                  "name"  => "varbinary_type",
 832                                  "type"  => "string",
 833                                  "len"   => '20',
 834                                  "flags" => "binary"),
 835                            array("table" => "data_types",
 836                                  "name"  => "tinyblob_type",
 837                                  "type"  => "blob",
 838                                  "len"   => '255',
 839                                  "flags" => "blob binary"),
 840                            array("table" => "data_types",
 841                                  "name"  => "tinytext_type",
 842                                  "type"  => "blob",
 843                                  "len"   => '255',
 844                                  "flags" => "blob"),
 845                            array("table" => "data_types",
 846                                  "name"  => "blob_type",
 847                                  "type"  => "blob",
 848                                  "len"   => '65535',
 849                                  "flags" => "blob binary"),
 850                            array("table" => "data_types",
 851                                  "name"  => "text_type",
 852                                  "type"  => "blob",
 853                                  "len"   => '65535',
 854                                  "flags" => "blob"),
 855                            array("table" => "data_types",
 856                                  "name"  => "mediumblob_type",
 857                                  "type"  => "blob",
 858                                  "len"   => '16777215',
 859                                  "flags" => "blob binary"),
 860                            array("table" => "data_types",
 861                                  "name"  => "mediumtext_type",
 862                                  "type"  => "blob",
 863                                  "len"   => '16777215',
 864                                  "flags" => "blob"),
 865                            array("table" => "data_types",
 866                                  "name"  => "longblob_type",
 867                                  "type"  => "blob",
 868                                  "len"   => '-1',
 869                                  "flags" => "blob binary"),
 870                            array("table" => "data_types",
 871                                  "name"  => "longtext_type",
 872                                  "type"  => "blob",
 873                                  "len"   => '-1',
 874                                  "flags" => "blob"),
 875                            array("table" => "data_types",
 876                                  "name"  => "enum_type",
 877                                  "type"  => "string",
 878                                  "len"   => '3',
 879                                  "flags" => "enum"),
 880                            array("table" => "data_types",
 881                                  "name"  => "set_type",
 882                                  "type"  => "string",
 883                                  "len"   => '7',
 884                                  "flags" => "set"),
 885                            ),
 886                      'data' =>
 887                      array()
 888                      ),
 889                );
 890  
 891      /**
 892       * Run-time configuration options
 893       *
 894       * @var array
 895       * @see DB_common::setOption()
 896       */
 897      var $options = array(
 898          'result_buffering' => 500,
 899          'persistent' => false,
 900          'ssl' => false,
 901          'debug' => 0,
 902          'seqname_format' => '%s_seq',
 903          'autofree' => false,
 904          'portability' => DB_PORTABILITY_NONE,
 905          'optimize' => 'performance',  // Deprecated.  Use 'portability'.
 906      );
 907  
 908      /**
 909       *  List of expected queries and returns
 910       */
 911      private $expected_list = null;
 912  
 913      /**
 914       *  Cursor in list of expected queries and returns
 915       */
 916      private $expected_list_cursor = null;
 917  
 918      /**
 919       *  Expected query
 920       *  @var string
 921       */
 922      private $expected_query = null;
 923  
 924      /**
 925       *  Result to be returned from expected query
 926       *  @var string
 927       */
 928      private $expected_result = null;
 929  
 930      /**
 931       * This constructor calls <kbd>$this->PEAR('DB_Error')</kbd>
 932       *
 933       * @return void
 934       */
 935      function DB_common()
 936      {
 937          $this->PEAR('DB_Error');
 938      }
 939  
 940      /**
 941       * Automatically indicates which properties should be saved
 942       * when PHP's serialize() function is called
 943       *
 944       * @return array  the array of properties names that should be saved
 945       *  @todo Implement mock DB_common::__sleep
 946       */
 947      function __sleep()
 948      {
 949  //        if ($this->connection) {
 950  //            // Don't disconnect(), people use serialize() for many reasons
 951  //            $this->was_connected = true;
 952  //        } else {
 953  //            $this->was_connected = false;
 954  //        }
 955  //        if (isset($this->autocommit)) {
 956  //            return array('autocommit',
 957  //                         'dbsyntax',
 958  //                         'dsn',
 959  //                         'features',
 960  //                         'fetchmode',
 961  //                         'fetchmode_object_class',
 962  //                         'options',
 963  //                         'was_connected',
 964  //                   );
 965  //        } else {
 966  //            return array('dbsyntax',
 967  //                         'dsn',
 968  //                         'features',
 969  //                         'fetchmode',
 970  //                         'fetchmode_object_class',
 971  //                         'options',
 972  //                         'was_connected',
 973  //                   );
 974  //        }
 975      }
 976  
 977      /**
 978       * Automatically reconnects to the database when PHP's unserialize()
 979       * function is called
 980       *
 981       * @return void
 982       *  @todo Implement mock DB_common::__wakeup
 983       */
 984      function __wakeup()
 985      {
 986  //        if ($this->was_connected) {
 987  //            $this->connect($this->dsn, $this->options);
 988  //        }
 989      }
 990  
 991      /**
 992       * Automatic string conversion for PHP 5
 993       *
 994       * @return string  a string describing the current PEAR DB object
 995       *  @todo Implement mock DB_common::__toString
 996       */
 997      public function __toString()
 998      {
 999  //        $info = strtolower(get_class($this));
1000  //        $info .=  ': (phptype=' . $this->phptype .
1001  //                  ', dbsyntax=' . $this->dbsyntax .
1002  //                  ')';
1003  //        if ($this->connection) {
1004  //            $info .= ' [connected]';
1005  //        }
1006  //        return $info;
1007      }
1008  
1009      /**
1010       * Quotes a string so it can be safely used as a table or column name
1011       *
1012       * @param string $str  the identifier name to be quoted
1013       * @return string  the quoted identifier
1014       */
1015      public function quoteIdentifier($str)
1016      {
1017          return '"' . str_replace('"', '""', $str) . '"';
1018      }
1019  
1020      /**
1021       * Formats input so it can be safely used in a query
1022       *
1023       * @see DB_common::escapeSimple()
1024       *  @todo Implement mock DB_common::quoteSmart
1025       */
1026      public function quoteSmart($in)
1027      {
1028  //        if (is_int($in) || is_double($in)) {
1029  //            return $in;
1030  //        } elseif (is_bool($in)) {
1031  //            return $in ? 1 : 0;
1032  //        } elseif (is_null($in)) {
1033  //            return 'NULL';
1034  //        } else {
1035  //            return "'" . $this->escapeSimple($in) . "'";
1036  //        }
1037      }
1038  
1039      /**
1040       * Escapes a string according to the current DBMS's standards
1041       *
1042       * @param string $str  the string to be escaped
1043       * @return string  the escaped string
1044       * @see DB_common::quoteSmart()
1045       *  @todo Implement mock DB_common::escapeSimple
1046       */
1047      public function escapeSimple($str)
1048      {
1049  //        return str_replace("'", "''", $str);
1050      }
1051  
1052      /**
1053       * Tells whether the present driver supports a given feature
1054       *
1055       * @param string $feature  the feature you're curious about
1056       * @return bool  whether this driver supports $feature
1057       *  @todo Implement mock DB_common::provides
1058       */
1059      public function provides($feature)
1060      {
1061  //        return $this->features[$feature];
1062      }
1063  
1064      /**
1065       * Sets the fetch mode that should be used by default for query results
1066       *
1067       * @param integer $fetchmode    DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC
1068       *                               or DB_FETCHMODE_OBJECT
1069       * @param string $object_class  the class name of the object to be returned
1070       *                               by the fetch methods when the
1071       *                               DB_FETCHMODE_OBJECT mode is selected.
1072       *                               If no class is specified by default a cast
1073       *                               to object from the assoc array row will be
1074       *                               done.  There is also the posibility to use
1075       *                               and extend the 'DB_row' class.
1076       *
1077       * @see DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT
1078       *  @todo Implement mock DB_common::setFetchMode
1079       */
1080      public function setFetchMode($fetchmode, $object_class = 'stdClass')
1081      {
1082  //        switch ($fetchmode) {
1083  //            case DB_FETCHMODE_OBJECT:
1084  //                $this->fetchmode_object_class = $object_class;
1085  //            case DB_FETCHMODE_ORDERED:
1086  //            case DB_FETCHMODE_ASSOC:
1087  //                $this->fetchmode = $fetchmode;
1088  //                break;
1089  //            default:
1090  //                return $this->raiseError('invalid fetchmode mode');
1091  //        }
1092      }
1093  
1094      /**
1095       * Sets run-time configuration options for PEAR DB
1096       *
1097       * @param string $option option name
1098       * @param mixed  $value value for the option
1099       * @return int  DB_OK on success.  A DB_Error object on failure.
1100       * @see DB_common::$options
1101       *  @todo Implement mock DB_common::setOption
1102       */
1103      public function setOption($option, $value)
1104      {
1105          if (isset($this->options[$option])) {
1106              $this->options[$option] = $value;
1107              return DB_OK;
1108          }
1109          PHPUnit2_Framework_Assert::fail("DB_common::setOption called"
1110                                          ." with unknown option $option");
1111      }
1112  
1113      /**
1114       * Returns the value of an option
1115       *
1116       * @param string $option  the option name you're curious about
1117       * @return mixed  the option's value
1118       *  @todo Implement mock DB_common::getOption
1119       */
1120      public function getOption($option)
1121      {
1122  //        if (isset($this->options[$option])) {
1123  //            return $this->options[$option];
1124  //        }
1125  //        return $this->raiseError("unknown option $option");
1126      }
1127  
1128      /**
1129       * Prepares a query for multiple execution with execute()
1130       *
1131       * @param string $query  the query to be prepared
1132       * @return mixed  DB statement resource on success. A DB_Error object
1133       *                 on failure.
1134       * @see DB_common::execute()
1135       *  @todo Implement mock DB_common::prepare
1136       */
1137      public function prepare($query)
1138      {
1139          PHPUnit2_Framework_Assert::fail("DB does not support"
1140                                          . " multiple execution");
1141  //        $tokens   = preg_split('/((?<!\\\)[&?!])/', $query, -1,
1142  //                               PREG_SPLIT_DELIM_CAPTURE);
1143  //        $token     = 0;
1144  //        $types     = array();
1145  //        $newtokens = array();
1146  //
1147  //        foreach ($tokens as $val) {
1148  //            switch ($val) {
1149  //                case '?':
1150  //                    $types[$token++] = DB_PARAM_SCALAR;
1151  //                    break;
1152  //                case '&':
1153  //                    $types[$token++] = DB_PARAM_OPAQUE;
1154  //                    break;
1155  //                case '!':
1156  //                    $types[$token++] = DB_PARAM_MISC;
1157  //                    break;
1158  //                default:
1159  //                    $newtokens[] = preg_replace('/\\\([&?!])/', "\\1", $val);
1160  //            }
1161  //        }
1162  //
1163  //        $this->prepare_tokens[] = &$newtokens;
1164  //        end($this->prepare_tokens);
1165  //
1166  //        $k = key($this->prepare_tokens);
1167  //        $this->prepare_types[$k] = $types;
1168  //        $this->prepared_queries[$k] = implode(' ', $newtokens);
1169  //
1170  //        return $k;
1171      }
1172  
1173  
1174      /**
1175       * Automaticaly generates an insert or update query and pass it to
1176       * prepare() 
1177       *
1178       * @param string $table         the table name
1179       * @param array  $table_fields  the array of field names
1180       * @param int    $mode          a type of query to make:
1181       *                               DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
1182       * @param string $where         for update queries: the WHERE clause to
1183       *                               append to the SQL statement.  Don't
1184       *                               include the "WHERE" keyword.
1185       *
1186       * @return resource  the query handle
1187       * @uses DB_common::prepare(), DB_common::buildManipSQL()
1188       *  @todo Implement mock DB_common::autoPrepare
1189       */
1190      public function autoPrepare($table, $table_fields, $mode = DB_AUTOQUERY_INSERT,
1191                           $where = false)
1192      {
1193  //        $query = $this->buildManipSQL($table, $table_fields, $mode, $where);
1194  //        if (DB::isError($query)) {
1195  //            return $query;
1196  //        }
1197  //        return $this->prepare($query);
1198      }
1199  
1200      /**
1201       * Automaticaly generates an insert or update query and call prepare()
1202       * and execute() with it
1203       *
1204       * @param string $table         the table name
1205       * @param array  $fields_values the associative array where $key is a
1206       *                               field name and $value its value
1207       * @param int    $mode          a type of query to make:
1208       *                               DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
1209       * @param string $where         for update queries: the WHERE clause to
1210       *                               append to the SQL statement.  Don't
1211       *                               include the "WHERE" keyword.
1212       *
1213       * @return mixed  a new DB_result object for successful SELECT queries
1214       *                 or DB_OK for successul data manipulation queries.
1215       *                 A DB_Error object on failure.
1216       *
1217       * @uses DB_common::autoPrepare(), DB_common::execute()
1218       *  @todo Implement mock DB_common::autoExecute
1219       */
1220      public function autoExecute($table, $fields_values, $mode = DB_AUTOQUERY_INSERT,
1221                           $where = false)
1222      {
1223          PHPUnit2_Framework_Assert::fail("DB does not support"
1224                                          . " multiple execution");
1225  //        $sth = $this->autoPrepare($table, array_keys($fields_values), $mode,
1226  //                                  $where);
1227  //        if (DB::isError($sth)) {
1228  //            return $sth;
1229  //        }
1230  //        $ret =& $this->execute($sth, array_values($fields_values));
1231  //        $this->freePrepared($sth);
1232  //        return $ret;
1233      }
1234  
1235      /**
1236       * Produces an SQL query string for autoPrepare()
1237       *
1238       * @param string $table         the table name
1239       * @param array  $table_fields  the array of field names
1240       * @param int    $mode          a type of query to make:
1241       *                               DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
1242       * @param string $where         for update queries: the WHERE clause to
1243       *                               append to the SQL statement.  Don't
1244       *                               include the "WHERE" keyword.
1245       *
1246       * @return string  the sql query for autoPrepare()
1247       *  @todo Implement mock DB_common::buildManipSQL
1248       */
1249      public function buildManipSQL($table, $table_fields, $mode, $where = false)
1250      {
1251  //        if (count($table_fields) == 0) {
1252  //            return $this->raiseError(DB_ERROR_NEED_MORE_DATA);
1253  //        }
1254  //        $first = true;
1255  //        switch ($mode) {
1256  //            case DB_AUTOQUERY_INSERT:
1257  //                $values = '';
1258  //                $names = '';
1259  //                foreach ($table_fields as $value) {
1260  //                    if ($first) {
1261  //                        $first = false;
1262  //                    } else {
1263  //                        $names .= ',';
1264  //                        $values .= ',';
1265  //                    }
1266  //                    $names .= $value;
1267  //                    $values .= '?';
1268  //                }
1269  //                return "INSERT INTO $table ($names) VALUES ($values)";
1270  //            case DB_AUTOQUERY_UPDATE:
1271  //                $set = '';
1272  //                foreach ($table_fields as $value) {
1273  //                    if ($first) {
1274  //                        $first = false;
1275  //                    } else {
1276  //                        $set .= ',';
1277  //                    }
1278  //                    $set .= "$value = ?";
1279  //                }
1280  //                $sql = "UPDATE $table SET $set";
1281  //                if ($where) {
1282  //                    $sql .= " WHERE $where";
1283  //                }
1284  //                return $sql;
1285  //            default:
1286  //                return $this->raiseError(DB_ERROR_SYNTAX);
1287  //        }
1288      }
1289  
1290      /**
1291       * Executes a DB statement prepared with prepare()
1292       *
1293       * @param resource $stmt  a DB statement resource returned from prepare()
1294       * @param mixed    $data  array, string or numeric data to be used in
1295       *                         execution of the statement.  Quantity of items
1296       *                         passed must match quantity of placeholders in
1297       *                         query:  meaning 1 placeholder for non-array
1298       *                         parameters or 1 placeholder per array element.
1299       *
1300       * @return mixed  a new DB_result object for successful SELECT queries
1301       *                 or DB_OK for successul data manipulation queries.
1302       *                 A DB_Error object on failure.
1303       *
1304       * @see DB_common::prepare()
1305       *  @todo Implement mock DB_common::execute
1306       */
1307      public function &execute($stmt, $data = array())
1308      {
1309          PHPUnit2_Framework_Assert::fail("DB does not support"
1310                                          . " multiple execution");
1311  //        $realquery = $this->executeEmulateQuery($stmt, $data);
1312  //        if (DB::isError($realquery)) {
1313  //            return $realquery;
1314  //        }
1315  //        $result = $this->simpleQuery($realquery);
1316  //
1317  //        if ($result === DB_OK || DB::isError($result)) {
1318  //            return $result;
1319  //        } else {
1320  //            $tmp =& new DB_result($this, $result);
1321  //            return $tmp;
1322  //        }
1323      }
1324  
1325      /**
1326       * Emulates executing prepared statements if the DBMS not support them
1327       *
1328       * @param resource $stmt  a DB statement resource returned from execute()
1329       * @param mixed    $data  array, string or numeric data to be used in
1330       *                         execution of the statement.  Quantity of items
1331       *                         passed must match quantity of placeholders in
1332       *                         query:  meaning 1 placeholder for non-array
1333       *                         parameters or 1 placeholder per array element.
1334       *
1335       * @return mixed  a string containing the real query run when emulating
1336       *                 prepare/execute.  A DB_Error object on failure.
1337       *
1338       * @see DB_common::execute()
1339       *  @todo Implement mock DB_common::executeEmulateQuery
1340       */
1341      protected function executeEmulateQuery($stmt, $data = array())
1342      {
1343          PHPUnit2_Framework_Assert::fail("DB does not support"
1344                                          . " multiple execution");
1345  //        $stmt = (int)$stmt;
1346  //        $data = (array)$data;
1347  //        $this->last_parameters = $data;
1348  //
1349  //        if (count($this->prepare_types[$stmt]) != count($data)) {
1350  //            $this->last_query = $this->prepared_queries[$stmt];
1351  //            return $this->raiseError(DB_ERROR_MISMATCH);
1352  //        }
1353  //
1354  //        $realquery = $this->prepare_tokens[$stmt][0];
1355  //
1356  //        $i = 0;
1357  //        foreach ($data as $value) {
1358  //            if ($this->prepare_types[$stmt][$i] == DB_PARAM_SCALAR) {
1359  //                $realquery .= $this->quoteSmart($value);
1360  //            } elseif ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) {
1361  //                $fp = @fopen($value, 'rb');
1362  //                if (!$fp) {
1363  //                    return $this->raiseError(DB_ERROR_ACCESS_VIOLATION);
1364  //                }
1365  //                $realquery .= $this->quoteSmart(fread($fp, filesize($value)));
1366  //                fclose($fp);
1367  //            } else {
1368  //                $realquery .= $value;
1369  //            }
1370  //
1371  //            $realquery .= $this->prepare_tokens[$stmt][++$i];
1372  //        }
1373  //
1374  //        return $realquery;
1375      }
1376  
1377      /**
1378       * Performs several execute() calls on the same statement handle
1379       *
1380       * @param resource $stmt  query handle from prepare()
1381       * @param array    $data  numeric array containing the
1382       *                         data to insert into the query
1383       * @return int  DB_OK on success.  A DB_Error object on failure.
1384       * @see DB_common::prepare(), DB_common::execute()
1385       *  @todo Implement mock DB_common::executeMultiple
1386       */
1387      function executeMultiple($stmt, $data)
1388      {
1389          PHPUnit2_Framework_Assert::fail("DB does not support"
1390                                          . " multiple execution");
1391  //        foreach ($data as $value) {
1392  //            $res =& $this->execute($stmt, $value);
1393  //            if (DB::isError($res)) {
1394  //                return $res;
1395  //            }
1396  //        }
1397  //        return DB_OK;
1398      }
1399  
1400      /**
1401       * Frees the internal resources associated with a prepared query
1402       *
1403       * @param resource $stmt           the prepared statement's PHP resource
1404       * @param bool     $free_resource  should the PHP resource be freed too?
1405       *                                  Use false if you need to get data
1406       *                                  from the result set later.
1407       * @return bool  TRUE on success, FALSE if $result is invalid
1408       * @see DB_common::prepare()
1409       *  @todo Implement mock DB_common::freePrepared
1410       */
1411      function freePrepared($stmt, $free_resource = true)
1412      {
1413          PHPUnit2_Framework_Assert::fail("DB does not support"
1414                                          . " multiple execution");
1415  //        $stmt = (int)$stmt;
1416  //        if (isset($this->prepare_tokens[$stmt])) {
1417  //            unset($this->prepare_tokens[$stmt]);
1418  //            unset($this->prepare_types[$stmt]);
1419  //            unset($this->prepared_queries[$stmt]);
1420  //            return true;
1421  //        }
1422  //        return false;
1423      }
1424  
1425      /**
1426       * Changes a query string for various DBMS specific reasons
1427       *
1428       * @param string $query  the query string to modify
1429       * @return string  the modified query string
1430       * @see DB_mysql::modifyQuery(), DB_oci8::modifyQuery(),
1431       *      DB_sqlite::modifyQuery()
1432       *  @todo Implement mock DB_common::modifyQuery
1433       */
1434      protected function modifyQuery($query)
1435      {
1436  //        return $query;
1437      }
1438  
1439      /**
1440       * Adds LIMIT clauses to a query string according to current DBMS standards
1441       *
1442       * @param string $query   the query to modify
1443       * @param int    $from    the row to start to fetching (0 = the first row)
1444       * @param int    $count   the numbers of rows to fetch
1445       * @param mixed  $params  array, string or numeric data to be used in
1446       *                         execution of the statement.  Quantity of items
1447       *                         passed must match quantity of placeholders in
1448       *                         query:  meaning 1 placeholder for non-array
1449       *                         parameters or 1 placeholder per array element.
1450       *
1451       * @return string  the query string with LIMIT clauses added
1452       *  @todo Implement mock DB_common::modifyLimitQuery
1453       */
1454      protected function modifyLimitQuery($query, $from, $count, $params = array())
1455      {
1456  //        return $query;
1457      }
1458  
1459      /**
1460       *  Set expected query and return
1461       *
1462       *  This is a test routine that does not exist in the PEAR DB package.
1463       *  @param string $expected Expected query
1464       *  @param string $result Result to be returned when expected
1465       *  query is received.
1466       */
1467      public function expect_query($expected, $result) {
1468          $this->expected_query = $expected;
1469          $this->expected_result = $result;
1470      }
1471  
1472      /**
1473       *  Set list of expected queries and returns
1474       *
1475       *  This is a test routine that does not exist in the PEAR DB package.
1476       *  @param string $list Expected queries and returns
1477       */
1478      public function expect_queries($list) {
1479          $this->expected_list = $list;
1480          $this->expected_list_cursor = 0;
1481          $this->expect_query($this->expected_list[0]['query'],
1482                              $this->expected_list[0]['result']);
1483      }
1484  
1485      /**
1486       *  Verify that all expected queries have been received
1487       *
1488       *  This is a test routine that does not exist in the PEAR DB package.
1489       */
1490      public function tally_queries() {
1491          if ($this->expected_list_cursor < count($this->expected_list)) {
1492              PHPUnit2_Framework_Assert::fail("DB_mysql::expected query was"
1493                            ." not received. expected $this->expected_query");
1494          }
1495      }
1496  
1497      /**
1498       * Sends a query to the database server
1499       *
1500       * @param string $query   the SQL query or the statement to prepare
1501       * @param mixed  $params  array, string or numeric data to be used in
1502       *                         execution of the statement.  Quantity of items
1503       *                         passed must match quantity of placeholders in
1504       *                         query:  meaning 1 placeholder for non-array
1505       *                         parameters or 1 placeholder per array element.
1506       *
1507       * @return mixed  a new DB_result object for successful SELECT queries
1508       *                 or DB_OK for successul data manipulation queries.
1509       *                 A DB_Error object on failure.
1510       *
1511       * @see DB_result, DB_common::prepare(), DB_common::execute()
1512       *  @todo Implement mock DB_common::query
1513       */
1514      public function &query($query, $params = array())
1515      {
1516          $params = (array)$params;
1517          if (sizeof($params) > 0) {
1518              PHPUnit2_Framework_Assert::fail("DB does not support"
1519                                              . " multiple execution");
1520          }
1521          if (!is_null($this->expected_list)) {
1522              //  We are working through a list of queries.  If the
1523              //  number of queries received is greater than the number
1524              //  on the list, that's an error
1525              if ($this->expected_list_cursor >= count($this->expected_list)) {
1526                  PHPUnit2_Framework_Assert::fail(
1527                                "DB_mysql::query called with"
1528                               ."$query, exceeding number of queries expected");
1529                  }            
1530          }
1531          if ($query != $this->expected_query) {
1532              PHPUnit2_Framework_Assert::fail('DB_mysql::query() called with'
1533                   .' "'.$query.'", expected "'.$this->expected_query.'"');
1534          }
1535          $result = $this->expected_result;
1536          if (!is_null($this->expected_list)) {
1537              //  More queries are expected.  Advance the cursor
1538              $this->expected_list_cursor++;
1539              $this->expect_query(
1540                $this->expected_list[$this->expected_list_cursor]['query'],
1541                $this->expected_list[$this->expected_list_cursor]['result']);
1542          }
1543          return $result;
1544  //        if (sizeof($params) > 0) {
1545  //            $sth = $this->prepare($query);
1546  //            if (DB::isError($sth)) {
1547  //                return $sth;
1548  //            }
1549  //            $ret =& $this->execute($sth, $params);
1550  //            $this->freePrepared($sth, false);
1551  //            return $ret;
1552  //        } else {
1553  //            $this->last_parameters = array();
1554  //            $result = $this->simpleQuery($query);
1555  //            if ($result === DB_OK || DB::isError($result)) {
1556  //                return $result;
1557  //            } else {
1558  //                $tmp =& new DB_result($this, $result);
1559  //                return $tmp;
1560  //            }
1561  //        }
1562      }
1563  
1564      /**
1565       * Generates and executes a LIMIT query
1566       *
1567       * @param string $query   the query
1568       * @param intr   $from    the row to start to fetching (0 = the first row)
1569       * @param int    $count   the numbers of rows to fetch
1570       * @param mixed  $params  array, string or numeric data to be used in
1571       *                         execution of the statement.  Quantity of items
1572       *                         passed must match quantity of placeholders in
1573       *                         query:  meaning 1 placeholder for non-array
1574       *                         parameters or 1 placeholder per array element.
1575       *
1576       * @return mixed  a new DB_result object for successful SELECT queries
1577       *                 or DB_OK for successul data manipulation queries.
1578       *                 A DB_Error object on failure.
1579       *  @todo Implement mock DB_common::limitQuery
1580       */
1581      public function &limitQuery($query, $from, $count, $params = array())
1582      {
1583  //        $query = $this->modifyLimitQuery($query, $from, $count, $params);
1584  //        if (DB::isError($query)){
1585  //            return $query;
1586  //        }
1587  //        $result =& $this->query($query, $params);
1588  //        if (is_a($result, 'DB_result')) {
1589  //            $result->setOption('limit_from', $from);
1590  //            $result->setOption('limit_count', $count);
1591  //        }
1592  //        return $result;
1593      }
1594  
1595      /**
1596       * Fetches the first column of the first row from a query result
1597       *
1598       * @param string $query   the SQL query
1599       * @param mixed  $params  array, string or numeric data to be used in
1600       *                         execution of the statement.  Quantity of items
1601       *                         passed must match quantity of placeholders in
1602       *                         query:  meaning 1 placeholder for non-array
1603       *                         parameters or 1 placeholder per array element.
1604       *
1605       * @return mixed  the returned value of the query.
1606       *                 A DB_Error object on failure.
1607       *  @todo Implement mock DB_common::getOne
1608       */
1609      function &getOne($query, $params = array())
1610      {
1611          return $this->query($query,$params);
1612  
1613  //            $sth = $this->prepare($query);
1614  //            if (DB::isError($sth)) {
1615  //                return $sth;
1616  //            }
1617  //            $res =& $this->execute($sth, $params);
1618  //            $this->freePrepared($sth);
1619  //        } else {
1620  //            $res =& $this->query($query);
1621  //        }
1622  //
1623  //        if (DB::isError($res)) {
1624  //            return $res;
1625  //        }
1626  //
1627  //        $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED);
1628  //        $res->free();
1629  //
1630  //        if ($err !== DB_OK) {
1631  //            return $err;
1632  //        }
1633  //
1634  //        return $row[0];
1635      }
1636  
1637      /**
1638       * Fetches the first row of data returned from a query result
1639       *
1640       * @param string $query   the SQL query
1641       * @param mixed  $params  array, string or numeric data to be used in
1642       *                         execution of the statement.  Quantity of items
1643       *                         passed must match quantity of placeholders in
1644       *                         query:  meaning 1 placeholder for non-array
1645       *                         parameters or 1 placeholder per array element.
1646       * @param int $fetchmode  the fetch mode to use
1647       *
1648       * @return array  the first row of results as an array.
1649       *                 A DB_Error object on failure.
1650       *  @todo Implement mock DB_common::getRow
1651       */
1652      public function &getRow($query, $params = array(),
1653                       $fetchmode = DB_FETCHMODE_DEFAULT)
1654      {
1655  //        // compat check, the params and fetchmode parameters used to
1656  //        // have the opposite order
1657  //        if (!is_array($params)) {
1658  //            if (is_array($fetchmode)) {
1659  //                if ($params === null) {
1660  //                    $tmp = DB_FETCHMODE_DEFAULT;
1661  //                } else {
1662  //                    $tmp = $params;
1663  //                }
1664  //                $params = $fetchmode;
1665  //                $fetchmode = $tmp;
1666  //            } elseif ($params !== null) {
1667  //                $fetchmode = $params;
1668  //                $params = array();
1669  //            }
1670  //        }
1671  //        // modifyLimitQuery() would be nice here, but it causes BC issues
1672  //        if (sizeof($params) > 0) {
1673  //            $sth = $this->prepare($query);
1674  //            if (DB::isError($sth)) {
1675  //                return $sth;
1676  //            }
1677  //            $res =& $this->execute($sth, $params);
1678  //            $this->freePrepared($sth);
1679  //        } else {
1680  //            $res =& $this->query($query);
1681  //        }
1682  //
1683  //        if (DB::isError($res)) {
1684  //            return $res;
1685  //        }
1686  //
1687  //        $err = $res->fetchInto($row, $fetchmode);
1688  //
1689  //        $res->free();
1690  //
1691  //        if ($err !== DB_OK) {
1692  //            return $err;
1693  //        }
1694  //
1695  //        return $row;
1696      }
1697  
1698      /**
1699       * Fetches a single column from a query result and returns it as an
1700       * indexed array
1701       *
1702       * @param string $query   the SQL query
1703       * @param mixed  $col     which column to return (integer [column number,
1704       *                         starting at 0] or string [column name])
1705       * @param mixed  $params  array, string or numeric data to be used in
1706       *                         execution of the statement.  Quantity of items
1707       *                         passed must match quantity of placeholders in
1708       *                         query:  meaning 1 placeholder for non-array
1709       *                         parameters or 1 placeholder per array element.
1710       *
1711       * @return array  the results as an array.  A DB_Error object on failure.
1712       *
1713       * @see DB_common::query()
1714       *  @todo Implement mock DB_common::getCol
1715       */
1716      public function &getCol($query, $col = 0, $params = array())
1717      {
1718  //        $params = (array)$params;
1719  //        if (sizeof($params) > 0) {
1720  //            $sth = $this->prepare($query);
1721  //
1722  //            if (DB::isError($sth)) {
1723  //                return $sth;
1724  //            }
1725  //
1726  //            $res =& $this->execute($sth, $params);
1727  //            $this->freePrepared($sth);
1728  //        } else {
1729  //            $res =& $this->query($query);
1730  //        }
1731  //
1732  //        if (DB::isError($res)) {
1733  //            return $res;
1734  //        }
1735  //
1736  //        $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC;
1737  //
1738  //        if (!is_array($row = $res->fetchRow($fetchmode))) {
1739  //            $ret = array();
1740  //        } else {
1741  //            if (!array_key_exists($col, $row)) {
1742  //                $ret =& $this->raiseError(DB_ERROR_NOSUCHFIELD);
1743  //            } else {
1744  //                $ret = array($row[$col]);
1745  //                while (is_array($row = $res->fetchRow($fetchmode))) {
1746  //                    $ret[] = $row[$col];
1747  //                }
1748  //            }
1749  //        }
1750  //
1751  //        $res->free();
1752  //
1753  //        if (DB::isError($row)) {
1754  //            $ret = $row;
1755  //        }
1756  //
1757  //        return $ret;
1758      }
1759  
1760      /**
1761       * Fetches an entire query result and returns it as an
1762       * associative array using the first column as the key
1763       *
1764       * @param string $query        the SQL query
1765       * @param bool   $force_array  used only when the query returns
1766       *                              exactly two columns.  If true, the values
1767       *                              of the returned array will be one-element
1768       *                              arrays instead of scalars.
1769       * @param mixed  $params       array, string or numeric data to be used in
1770       *                              execution of the statement.  Quantity of
1771       *                              items passed must match quantity of
1772       *                              placeholders in query:  meaning 1
1773       *                              placeholder for non-array parameters or
1774       *                              1 placeholder per array element.
1775       * @param int   $fetchmode     the fetch mode to use
1776       * @param bool  $group         if true, the values of the returned array
1777       *                              is wrapped in another array.  If the same
1778       *                              key value (in the first column) repeats
1779       *                              itself, the values will be appended to
1780       *                              this array instead of overwriting the
1781       *                              existing values.
1782       *
1783       * @return array  the associative array containing the query results.
1784       *                A DB_Error object on failure.
1785       *  @todo Implement mock DB_common::getAssoc
1786       */
1787      public function &getAssoc($query, $force_array = false, $params = array(),
1788                         $fetchmode = DB_FETCHMODE_DEFAULT, $group = false)
1789      {
1790  //        $params = (array)$params;
1791  //        if (sizeof($params) > 0) {
1792  //            $sth = $this->prepare($query);
1793  //
1794  //            if (DB::isError($sth)) {
1795  //                return $sth;
1796  //            }
1797  //
1798  //            $res =& $this->execute($sth, $params);
1799  //            $this->freePrepared($sth);
1800  //        } else {
1801  //            $res =& $this->query($query);
1802  //        }
1803  //
1804  //        if (DB::isError($res)) {
1805  //            return $res;
1806  //        }
1807  //        if ($fetchmode == DB_FETCHMODE_DEFAULT) {
1808  //            $fetchmode = $this->fetchmode;
1809  //        }
1810  //        $cols = $res->numCols();
1811  //
1812  //        if ($cols < 2) {
1813  //            $tmp =& $this->raiseError(DB_ERROR_TRUNCATED);
1814  //            return $tmp;
1815  //        }
1816  //
1817  //        $results = array();
1818  //
1819  //        if ($cols > 2 || $force_array) {
1820  //            // return array values
1821  //            // XXX this part can be optimized
1822  //            if ($fetchmode == DB_FETCHMODE_ASSOC) {
1823  //                while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) {
1824  //                    reset($row);
1825  //                    $key = current($row);
1826  //                    unset($row[key($row)]);
1827  //                    if ($group) {
1828  //                        $results[$key][] = $row;
1829  //                    } else {
1830  //                        $results[$key] = $row;
1831  //                    }
1832  //                }
1833  //            } elseif ($fetchmode == DB_FETCHMODE_OBJECT) {
1834  //                while ($row = $res->fetchRow(DB_FETCHMODE_OBJECT)) {
1835  //                    $arr = get_object_vars($row);
1836  //                    $key = current($arr);
1837  //                    if ($group) {
1838  //                        $results[$key][] = $row;
1839  //                    } else {
1840  //                        $results[$key] = $row;
1841  //                    }
1842  //                }
1843  //            } else {
1844  //                while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
1845  //                    // we shift away the first element to get
1846  //                    // indices running from 0 again
1847  //                    $key = array_shift($row);
1848  //                    if ($group) {
1849  //                        $results[$key][] = $row;
1850  //                    } else {
1851  //                        $results[$key] = $row;
1852  //                    }
1853  //                }
1854  //            }
1855  //            if (DB::isError($row)) {
1856  //                $results = $row;
1857  //            }
1858  //        } else {
1859  //            // return scalar values
1860  //            while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
1861  //                if ($group) {
1862  //                    $results[$row[0]][] = $row[1];
1863  //                } else {
1864  //                    $results[$row[0]] = $row[1];
1865  //                }
1866  //            }
1867  //            if (DB::isError($row)) {
1868  //                $results = $row;
1869  //            }
1870  //        }
1871  //
1872  //        $res->free();
1873  //
1874  //        return $results;
1875      }
1876  
1877      /**
1878       * Fetches all of the rows from a query result
1879       *
1880       * @param string $query      the SQL query
1881       * @param mixed  $params     array, string or numeric data to be used in
1882       *                            execution of the statement.  Quantity of
1883       *                            items passed must match quantity of
1884       *                            placeholders in query:  meaning 1
1885       *                            placeholder for non-array parameters or
1886       *                            1 placeholder per array element.
1887       * @param int    $fetchmode  the fetch mode to use:
1888       *                            + DB_FETCHMODE_ORDERED
1889       *                            + DB_FETCHMODE_ASSOC
1890       *                            + DB_FETCHMODE_ORDERED | DB_FETCHMODE_FLIPPED
1891       *                            + DB_FETCHMODE_ASSOC | DB_FETCHMODE_FLIPPED
1892       *
1893       * @return array  the nested array.  A DB_Error object on failure.
1894       *  @todo Implement mock DB_common::getAll
1895       */
1896      public function &getAll($query, $params = array(),
1897                       $fetchmode = DB_FETCHMODE_DEFAULT)
1898      {
1899  //        // compat check, the params and fetchmode parameters used to
1900  //        // have the opposite order
1901  //        if (!is_array($params)) {
1902  //            if (is_array($fetchmode)) {
1903  //                if ($params === null) {
1904  //                    $tmp = DB_FETCHMODE_DEFAULT;
1905  //                } else {
1906  //                    $tmp = $params;
1907  //                }
1908  //                $params = $fetchmode;
1909  //                $fetchmode = $tmp;
1910  //            } elseif ($params !== null) {
1911  //                $fetchmode = $params;
1912  //                $params = array();
1913  //            }
1914  //        }
1915  //
1916  //        if (sizeof($params) > 0) {
1917  //            $sth = $this->prepare($query);
1918  //
1919  //            if (DB::isError($sth)) {
1920  //                return $sth;
1921  //            }
1922  //
1923  //            $res =& $this->execute($sth, $params);
1924  //            $this->freePrepared($sth);
1925  //        } else {
1926  //            $res =& $this->query($query);
1927  //        }
1928  //
1929  //        if ($res === DB_OK || DB::isError($res)) {
1930  //            return $res;
1931  //        }
1932  //
1933  //        $results = array();
1934  //        while (DB_OK === $res->fetchInto($row, $fetchmode)) {
1935  //            if ($fetchmode & DB_FETCHMODE_FLIPPED) {
1936  //                foreach ($row as $key => $val) {
1937  //                    $results[$key][] = $val;
1938  //                }
1939  //            } else {
1940  //                $results[] = $row;
1941  //            }
1942  //        }
1943  //
1944  //        $res->free();
1945  //
1946  //        if (DB::isError($row)) {
1947  //            $tmp =& $this->raiseError($row);
1948  //            return $tmp;
1949  //        }
1950  //        return $results;
1951      }
1952  
1953      /**
1954       * Enables or disables automatic commits
1955       *
1956       * @param bool $onoff  true turns it on, false turns it off
1957       * @return int  DB_OK on success.  A DB_Error object if the driver
1958       *               doesn't support auto-committing transactions.
1959       *  @todo Implement mock DB_common::autoCommit
1960       */
1961      public function autoCommit($onoff = false)
1962      {
1963  //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1964      }
1965  
1966      /**
1967       * Commits the current transaction
1968       *
1969       * @return int  DB_OK on success.  A DB_Error object on failure.
1970       *  @todo Implement mock DB_common::commit
1971       */
1972      public function commit()
1973      {
1974  //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1975      }
1976  
1977      /**
1978       * Reverts the current transaction
1979       *
1980       * @return int  DB_OK on success.  A DB_Error object on failure.
1981       *  @todo Implement mock DB_common::rollback
1982       */
1983      public function rollback()
1984      {
1985  //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1986      }
1987  
1988      /**
1989       * Determines the number of rows in a query result
1990       *
1991       * @param resource $result  the query result idenifier produced by PHP
1992       * @return int  the number of rows.  A DB_Error object on failure.
1993       *  @todo Implement mock DB_common::numRows
1994       */
1995      public function numRows($result)
1996      {
1997  //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1998      }
1999  
2000      /**
2001       * Determines the number of rows affected by a data maniuplation query
2002       *
2003       * 0 is returned for queries that don't manipulate data.
2004       *
2005       * @return int  the number of rows.  A DB_Error object on failure.
2006       *  @todo Implement mock DB_common::affectedRows
2007       */
2008      public function affectedRows()
2009      {
2010  //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
2011      }
2012  
2013      /**
2014       * Generates the name used inside the database for a sequence
2015       *
2016       * @param string $sqn  the sequence's public name
2017       * @return string  the sequence's name in the backend
2018       * @see DB_common::createSequence(), DB_common::dropSequence(),
2019       *      DB_common::nextID(), DB_common::setOption()
2020       *  @todo Implement mock DB_common::getSequenceName
2021       */
2022      protected function getSequenceName($sqn)
2023      {
2024  //        return sprintf($this->getOption('seqname_format'),
2025  //                       preg_replace('/[^a-z0-9_.]/i', '_', $sqn));
2026      }
2027  
2028      /**
2029       * Returns the next free id in a sequence
2030       *
2031       * @param string  $seq_name  name of the sequence
2032       * @param boolean $ondemand  when true, the seqence is automatically
2033       *                            created if it does not exist
2034       *
2035       * @return int  the next id number in the sequence.
2036       *               A DB_Error object on failure.
2037       *
2038       * @see DB_common::createSequence(), DB_common::dropSequence(),
2039       *      DB_common::getSequenceName()
2040       *  @todo Implement mock DB_common::nextID
2041       */
2042      public function nextId($seq_name, $ondemand = true)
2043      {
2044  //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
2045      }
2046  
2047      /**
2048       * Creates a new sequence
2049       *
2050       * @param string $seq_name  name of the new sequence
2051       * @return int  DB_OK on success.  A DB_Error object on failure.
2052       * @see DB_common::dropSequence(), DB_common::getSequenceName(),
2053       *      DB_common::nextID()
2054       *  @todo Implement mock DB_common::createSequence
2055       */
2056      public function createSequence($seq_name)
2057      {
2058  //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
2059      }
2060  
2061      /**
2062       * Deletes a sequence
2063       *
2064       * @param string $seq_name  name of the sequence to be deleted
2065       * @return int  DB_OK on success.  A DB_Error object on failure.
2066       * @see DB_common::createSequence(), DB_common::getSequenceName(),
2067       *      DB_common::nextID()
2068       *  @todo Implement mock DB_common::dropSequence
2069       */
2070      public function dropSequence($seq_name)
2071      {
2072  //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
2073      }
2074  
2075      /**
2076       * Communicates an error and invoke error callbacks, etc
2077       *
2078       * Basically a wrapper for PEAR::raiseError without the message string.
2079       *
2080       * @param mixed   integer error code, or a PEAR error object (all
2081       *                 other parameters are ignored if this parameter is
2082       *                 an object
2083       * @param int     error mode, see PEAR_Error docs
2084       * @param mixed   if error mode is PEAR_ERROR_TRIGGER, this is the
2085       *                 error level (E_USER_NOTICE etc).  If error mode is
2086       *                 PEAR_ERROR_CALLBACK, this is the callback function,
2087       *                 either as a function name, or as an array of an
2088       *                 object and method name.  For other error modes this
2089       *                 parameter is ignored.
2090       * @param string  extra debug information.  Defaults to the last
2091       *                 query and native error code.
2092       * @param mixed   native error code, integer or string depending the
2093       *                 backend
2094       *
2095       * @return object  the PEAR_Error object
2096       * @see PEAR_Error
2097       *  @todo Implement mock DB_common::raiseError
2098       */
2099      public function &raiseError($code = DB_ERROR, $mode = null, $options = null,
2100                           $userinfo = null, $nativecode = null)
2101      {
2102  //        // The error is yet a DB error object
2103  //        if (is_object($code)) {
2104  //            // because we the static PEAR::raiseError, our global
2105  //            // handler should be used if it is set
2106  //            if ($mode === null && !empty($this->_default_error_mode)) {
2107  //                $mode    = $this->_default_error_mode;
2108  //                $options = $this->_default_error_options;
2109  //            }
2110  //            $tmp = PEAR::raiseError($code, null, $mode, $options,
2111  //                                    null, null, true);
2112  //            return $tmp;
2113  //        }
2114  //
2115  //        if ($userinfo === null) {
2116  //            $userinfo = $this->last_query;
2117  //        }
2118  //
2119  //        if ($nativecode) {
2120  //            $userinfo .= ' [nativecode=' . trim($nativecode) . ']';
2121  //        } else {
2122  //            $userinfo .= ' [DB Error: ' . DB::errorMessage($code) . ']';
2123  //        }
2124  //
2125  //        $tmp = PEAR::raiseError(null, $code, $mode, $options, $userinfo,
2126  //                                'DB_Error', true);
2127  //        return $tmp;
2128      }
2129  
2130      /**
2131       * Gets the DBMS' native error code produced by the last query
2132       *
2133       * @return mixed  the DBMS' error code.  A DB_Error object on failure.
2134       *  @todo Implement mock DB_common::errorNative
2135       */
2136      public function errorNative()
2137      {
2138  //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
2139      }
2140  
2141      /**
2142       * Maps native error codes to DB's portable ones
2143       *
2144       * Uses the <var>$errorcode_map</var> property defined in each driver.
2145       *
2146       * @param string|int $nativecode  the error code returned by the DBMS
2147       *
2148       * @return int  the portable DB error code.  Return DB_ERROR if the
2149       *               current driver doesn't have a mapping for the
2150       *               $nativecode submitted.
2151       *  @todo Implement mock DB_common::errorCode
2152       */
2153      public function errorCode($nativecode)
2154      {
2155  //        if (isset($this->errorcode_map[$nativecode])) {
2156  //            return $this->errorcode_map[$nativecode];
2157  //        }
2158          // Fall back to DB_ERROR if there was no mapping.
2159          return DB_ERROR;
2160      }
2161  
2162      /**
2163       * Maps a DB error code to a textual message
2164       *
2165       * @param integer $dbcode  the DB error code
2166       * @return string  the error message corresponding to the error code
2167       *                  submitted.  FALSE if the error code is unknown.
2168       * @see DB::errorMessage()
2169       *  @todo Implement mock DB_common::errorMessage
2170       */
2171      public function errorMessage($dbcode)
2172      {
2173  //        return DB::errorMessage($this->errorcode_map[$dbcode]);
2174      }
2175  
2176      /**
2177       * Returns information about a table or a result set
2178       *
2179       * @param object|string  $result  DB_result object from a query or a
2180       *                                string containing the name of a table.
2181       *                                While this also accepts a query result
2182       *                                resource identifier, this behavior is
2183       *                                deprecated.
2184       * @param int  $mode   either unused or one of the tableInfo modes:
2185       *                     <kbd>DB_TABLEINFO_ORDERTABLE</kbd>,
2186       *                     <kbd>DB_TABLEINFO_ORDER</kbd> or
2187       *                     <kbd>DB_TABLEINFO_FULL</kbd> (which does both).
2188       *                     These are bitwise, so the first two can be
2189       *                     combined using <kbd>|</kbd>.
2190       *
2191       * @return array  an associative array with the information requested.
2192       *                 A DB_Error object on failure.
2193       *
2194       * @see DB_common::setOption()
2195       *  @todo Implement mock DB_common::tableInfo
2196       */
2197      public function tableInfo($result, $mode = null)
2198      {
2199          /*
2200           * If the DB_<driver> class has a tableInfo() method, that one
2201           * overrides this one.  But, if the driver doesn't have one,
2202           * this method runs and tells users about that fact.
2203           */
2204          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
2205      }
2206  
2207      /**
2208       * Lists internal database information
2209       *
2210       * @param string $type  type of information being sought.
2211       *                       Common items being sought are:
2212       *                       tables, databases, users, views, functions
2213       *                       Each DBMS's has its own capabilities.
2214       *
2215       * @return array  an array listing the items sought.
2216       *                 A DB DB_Error object on failure.
2217       *  @todo Implement mock DB_common::getListOf
2218       */
2219      public function getListOf($type)
2220      {
2221  //        $sql = $this->getSpecialQuery($type);
2222  //        if ($sql === null) {
2223  //            $this->last_query = '';
2224  //            return $this->raiseError(DB_ERROR_UNSUPPORTED);
2225  //        } elseif (is_int($sql) || DB::isError($sql)) {
2226  //            // Previous error
2227  //            return $this->raiseError($sql);
2228  //        } elseif (is_array($sql)) {
2229  //            // Already the result
2230  //            return $sql;
2231  //        }
2232  //        // Launch this query
2233  //        return $this->getCol($sql);
2234      }
2235  
2236      /**
2237       * Obtains the query string needed for listing a given type of objects
2238       *
2239       * @param string $type  the kind of objects you want to retrieve
2240       * @return string  the SQL query string or null if the driver doesn't
2241       *                  support the object type requested
2242       * @see DB_common::getListOf()
2243       *  @todo Implement mock DB_common::getSpecialQuery
2244       */
2245      protected function getSpecialQuery($type)
2246      {
2247  //        return $this->raiseError(DB_ERROR_UNSUPPORTED);
2248      }
2249  
2250      /**
2251       * Right-trims all strings in an array
2252       *
2253       * @param array $array  the array to be trimmed (passed by reference)
2254       * @return void
2255       */
2256      protected function _rtrimArrayValues(&$array)
2257      {
2258          foreach ($array as $key => $value) {
2259              if (is_string($value)) {
2260                  $array[$key] = rtrim($value);
2261              }
2262          }
2263      }
2264  
2265      /**
2266       * Converts all null values in an array to empty strings
2267       *
2268       * @param array  $array  the array to be de-nullified (passed by reference)
2269       * @return void
2270       */
2271      protected function _convertNullArrayValuesToEmpty(&$array)
2272      {
2273          foreach ($array as $key => $value) {
2274              if (is_null($value)) {
2275                  $array[$key] = '';
2276              }
2277          }
2278      }
2279  }
2280  
2281  /**
2282   *  Mock DB_Error
2283   *  @todo Implement mock DB_Error class
2284   */
2285  class DB_Error extends PEAR_Error
2286  {
2287      /**
2288       * DB_Error constructor
2289       *
2290       * @param mixed $code       DB error code, or string with error message
2291       * @param int   $mode       what "error mode" to operate in
2292       * @param int   $level      what error level to use for $mode &
2293       *                           PEAR_ERROR_TRIGGER
2294       * @param mixed $debuginfo  additional debug info, such as the last query
2295       * @see PEAR_Error
2296       *  @todo Implement DB_Error::constructor
2297       */
2298      function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN,
2299                        $level = E_USER_NOTICE, $debuginfo = null)
2300      {
2301  //        if (is_int($code)) {
2302  //            $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code,
2303  //                              $mode, $level, $debuginfo);
2304  //        } else {
2305  //            $this->PEAR_Error("DB Error: $code", DB_ERROR,
2306  //                              $mode, $level, $debuginfo);
2307  //        }
2308      }
2309  }
2310  
2311  /**
2312   *  Mock DB_result
2313   *  @todo Implement mock DB_result
2314   */
2315  class DB_result
2316  {
2317  
2318      /**
2319       * This constructor sets the object's properties
2320       *
2321       * @param object   &$dbh     the DB object reference
2322       * @param resource $result   the result resource id
2323       * @param array    $options  an associative array with result options
2324       * @return void
2325       *  @todo Implement mock DB_result::constructor
2326       */
2327      function DB_result(&$dbh, $result, $options = array())
2328      {
2329      }
2330  
2331      /**
2332       * Set options for the DB_result object
2333       *
2334       * @param string $key    the option to set
2335       * @param mixed  $value  the value to set the option to
2336       * @return void
2337       *  @todo Implement mock DB_result::setOption()
2338       */
2339      function setOption($key, $value = null)
2340      {
2341          switch ($key) {
2342              case 'limit_from':
2343  //                $this->limit_from = $value;
2344                  break;
2345              case 'limit_count':
2346  //                $this->limit_count = $value;
2347          }
2348      }
2349  
2350      /**
2351       * Fetch a row of data and return it by reference into an array
2352       *
2353       * @param int $fetchmode  the constant indicating how to format the data
2354       * @param int $rownum     the row number to fetch (index starts at 0)
2355       *
2356       * @return mixed  an array or object containing the row's data,
2357       *                 NULL when the end of the result set is reached
2358       *                 or a DB_Error object on failure.
2359       *
2360       * @see DB_common::setOption(), DB_common::setFetchMode()
2361       *  @todo Implement mock DB_result::fetchRow()
2362       */
2363      function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null)
2364      {
2365  //        if ($fetchmode === DB_FETCHMODE_DEFAULT) {
2366  //            $fetchmode = $this->fetchmode;
2367  //        }
2368  //        if ($fetchmode === DB_FETCHMODE_OBJECT) {
2369  //            $fetchmode = DB_FETCHMODE_ASSOC;
2370  //            $object_class = $this->fetchmode_object_class;
2371  //        }
2372  //        if ($this->limit_from !== null) {
2373  //            if ($this->row_counter === null) {
2374  //                $this->row_counter = $this->limit_from;
2375  //                // Skip rows
2376  //                if ($this->dbh->features['limit'] === false) {
2377  //                    $i = 0;
2378  //                    while ($i++ < $this->limit_from) {
2379  //                        $this->dbh->fetchInto($this->result, $arr, $fetchmode);
2380  //                    }
2381  //                }
2382  //            }
2383  //            if ($this->row_counter >= ($this->limit_from + $this->limit_count))
2384  //            {
2385  //                if ($this->autofree) {
2386  //                    $this->free();
2387  //                }
2388  //                $tmp = null;
2389  //                return $tmp;
2390  //            }
2391  //            if ($this->dbh->features['limit'] === 'emulate') {
2392  //                $rownum = $this->row_counter;
2393  //            }
2394  //            $this->row_counter++;
2395  //        }
2396  //        $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
2397  //        if ($res === DB_OK) {
2398  //            if (isset($object_class)) {
2399  //                // The default mode is specified in the
2400  //                // DB_common::fetchmode_object_class property
2401  //                if ($object_class == 'stdClass') {
2402  //                    $arr = (object) $arr;
2403  //                } else {
2404  //                    $arr = &new $object_class($arr);
2405  //                }
2406  //            }
2407  //            return $arr;
2408  //        }
2409  //        if ($res == null && $this->autofree) {
2410  //            $this->free();
2411  //        }
2412  //        return $res;
2413      }
2414  
2415      /**
2416       * Fetch a row of data into an array which is passed by reference
2417       *
2418       * @param array &$arr       the variable where the data should be placed
2419       * @param int   $fetchmode  the constant indicating how to format the data
2420       * @param int   $rownum     the row number to fetch (index starts at 0)
2421       * @return mixed  DB_OK if a row is processed, NULL when the end of the
2422       *                 result set is reached or a DB_Error object on failure
2423       *
2424       * @see DB_common::setOption(), DB_common::setFetchMode()
2425       *  @todo Implement mock DB_result::fetchInto()
2426       */
2427      function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null)
2428      {
2429  //        if ($fetchmode === DB_FETCHMODE_DEFAULT) {
2430  //            $fetchmode = $this->fetchmode;
2431  //        }
2432  //        if ($fetchmode === DB_FETCHMODE_OBJECT) {
2433  //            $fetchmode = DB_FETCHMODE_ASSOC;
2434  //            $object_class = $this->fetchmode_object_class;
2435  //        }
2436  //        if ($this->limit_from !== null) {
2437  //            if ($this->row_counter === null) {
2438  //                $this->row_counter = $this->limit_from;
2439  //                // Skip rows
2440  //                if ($this->dbh->features['limit'] === false) {
2441  //                    $i = 0;
2442  //                    while ($i++ < $this->limit_from) {
2443  //                        $this->dbh->fetchInto($this->result, $arr, $fetchmode);
2444  //                    }
2445  //                }
2446  //            }
2447  //            if ($this->row_counter >= (
2448  //                    $this->limit_from + $this->limit_count))
2449  //            {
2450  //                if ($this->autofree) {
2451  //                    $this->free();
2452  //                }
2453  //                return null;
2454  //            }
2455  //            if ($this->dbh->features['limit'] === 'emulate') {
2456  //                $rownum = $this->row_counter;
2457  //            }
2458  //
2459  //            $this->row_counter++;
2460  //        }
2461  //        $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
2462  //        if ($res === DB_OK) {
2463  //            if (isset($object_class)) {
2464  //                // default mode specified in the
2465  //                // DB_common::fetchmode_object_class property
2466  //                if ($object_class == 'stdClass') {
2467  //                    $arr = (object) $arr;
2468  //                } else {
2469  //                    $arr = new $object_class($arr);
2470  //                }
2471  //            }
2472  //            return DB_OK;
2473  //        }
2474  //        if ($res == null && $this->autofree) {
2475  //            $this->free();
2476  //        }
2477  //        return $res;
2478      }
2479  
2480      /**
2481       * Get the the number of columns in a result set
2482       *
2483       * @return int  the number of columns.  A DB_Error object on failure.
2484       *  @todo Implement mock DB_result::numCols()
2485       */
2486      function numCols()
2487      {
2488  //        return $this->dbh->numCols($this->result);
2489      }
2490  
2491      /**
2492       * Get the number of rows in a result set
2493       *
2494       * @return int  the number of rows.  A DB_Error object on failure.
2495       *  @todo Implement mock DB_result::numRows()
2496       */
2497      function numRows()
2498      {
2499  //        if ($this->dbh->features['numrows'] === 'emulate'
2500  //            && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS)
2501  //        {
2502  //            if ($this->dbh->features['prepare']) {
2503  //                $res = $this->dbh->query($this->query, $this->parameters);
2504  //            } else {
2505  //                $res = $this->dbh->query($this->query);
2506  //            }
2507  //            if (DB::isError($res)) {
2508  //                return $res;
2509  //            }
2510  //            $i = 0;
2511  //            while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) {
2512  //                $i++;
2513  //            }
2514  //            return $i;
2515  //        } else {
2516  //            return $this->dbh->numRows($this->result);
2517  //        }
2518      }
2519  
2520      /**
2521       * Get the next result if a batch of queries was executed
2522       *
2523       * @return bool  true if a new result is available or false if not
2524       *  @todo Implement mock DB_result::nextResult()
2525       */
2526      function nextResult()
2527      {
2528  //        return $this->dbh->nextResult($this->result);
2529      }
2530  
2531      /**
2532       * Frees the resources allocated for this result set
2533       *
2534       * @return bool  true on success.  A DB_Error object on failure.
2535       *  @todo Implement mock DB_result::free()
2536       */
2537      function free()
2538      {
2539  //        $err = $this->dbh->freeResult($this->result);
2540  //        if (DB::isError($err)) {
2541  //            return $err;
2542  //        }
2543  //        $this->result = false;
2544  //        $this->statement = false;
2545  //        return true;
2546      }
2547  
2548      /**
2549       * Determine the query string that created this result
2550       *
2551       * @return string  the query string
2552       *  @todo Implement mock DB_result::getQuery()
2553       */
2554      function getQuery()
2555      {
2556  //        return $this->query;
2557      }
2558  
2559      /**
2560       * Tells which row number is currently being processed
2561       *
2562       * @return integer  the current row being looked at.  Starts at 1.
2563       *  @todo Implement mock DB_result::getRowCounter()
2564       */
2565      function getRowCounter()
2566      {
2567  //        return $this->row_counter;
2568      }
2569  }
2570  
2571  /**
2572   *  Mock DB_row
2573   *  @todo Implement mock DB_row
2574   */
2575  class DB_row
2576  {
2577  
2578      /**
2579       * The constructor places a row's data into properties of this object
2580       *
2581       * @param array  the array containing the row's data
2582       * @return void
2583       *  @todo Implement mock DB_row constructor
2584       */
2585      function DB_row(&$arr)
2586      {
2587  //        foreach ($arr as $key => $value) {
2588  //            $this->$key = &$arr[$key];
2589  //      }
2590      }
2591  }
2592  
2593  /**
2594   *  Mock DB_mysql class
2595   */
2596  class DB_mysql extends DB_common
2597  {
2598  
2599      /**
2600       * This constructor calls <kbd>$this->DB_common()</kbd>
2601       *
2602       * @return void
2603       */
2604      function DB_mysql()
2605      {
2606          $this->DB_common();
2607      }
2608  
2609      /**
2610       * Connect to the database server, log in and open the database
2611       *
2612       * @param array $dsn         the data source name
2613       * @param bool  $persistent  should the connection be persistent?
2614       * @return int  DB_OK on success. A DB_Error object on failure.
2615       *  @todo Implement mock DB_mysql::connect()
2616       */
2617      function connect($dsn, $persistent = false)
2618      {
2619  //        if (!PEAR::loadExtension('mysql')) {
2620  //            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
2621  //        }
2622  //
2623  //        $this->dsn = $dsn;
2624  //        if ($dsn['dbsyntax']) {
2625  //            $this->dbsyntax = $dsn['dbsyntax'];
2626  //        }
2627  //
2628  //        $params = array();
2629  //        if ($dsn['protocol'] && $dsn['protocol'] == 'unix') {
2630  //            $params[0] = ':' . $dsn['socket'];
2631  //        } else {
2632  //            $params[0] = $dsn['hostspec'] ? $dsn['hostspec']
2633  //                         : 'localhost';
2634  //            if ($dsn['port']) {
2635  //                $params[0] .= ':' . $dsn['port'];
2636  //            }
2637  //        }
2638  //        $params[] = $dsn['username'] ? $dsn['username'] : null;
2639  //        $params[] = $dsn['password'] ? $dsn['password'] : null;
2640  //
2641  //        if (!$persistent) {
2642  //            if (isset($dsn['new_link'])
2643  //                && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true))
2644  //            {
2645  //                $params[] = true;
2646  //            } else {
2647  //                $params[] = false;
2648  //            }
2649  //        }
2650  //        if (version_compare(phpversion(), '4.3.0', '>=')) {
2651  //            $params[] = isset($dsn['client_flags'])
2652  //                        ? $dsn['client_flags'] : null;
2653  //        }
2654  //
2655  //        $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect';
2656  //
2657  //        $ini = ini_get('track_errors');
2658  //        $php_errormsg = '';
2659  //        if ($ini) {
2660  //            $this->connection = @call_user_func_array($connect_function,
2661  //                                                      $params);
2662  //        } else {
2663  //            ini_set('track_errors', 1);
2664  //            $this->connection = @call_user_func_array($connect_function,
2665  //                                                      $params);
2666  //            ini_set('track_errors', $ini);
2667  //        }
2668  //
2669  //        if (!$this->connection) {
2670  //            if (($err = @mysql_error()) != '') {
2671  //                return $this->raiseError(DB_ERROR_CONNECT_FAILED,
2672  //                                         null, null, null, 
2673  //                                         $err);
2674  //            } else {
2675  //                return $this->raiseError(DB_ERROR_CONNECT_FAILED,
2676  //                                         null, null, null,
2677  //                                         $php_errormsg);
2678  //            }
2679  //        }
2680  //
2681  //        if ($dsn['database']) {
2682  //            if (!@mysql_select_db($dsn['database'], $this->connection)) {
2683  //                return $this->mysqlRaiseError();
2684  //            }
2685  //            $this->_db = $dsn['database'];
2686  //        }
2687  //
2688  //        return DB_OK;
2689      }
2690  
2691      /**
2692       * Disconnects from the database server
2693       *
2694       * @return bool  TRUE on success, FALSE on failure
2695       *  @todo Implement mock DB_mysql::disconnect()
2696       */
2697      function disconnect()
2698      {
2699  //        $ret = @mysql_close($this->connection);
2700  //        $this->connection = null;
2701  //        return $ret;
2702      }
2703  
2704      /**
2705       * Sends a query to the database server
2706       *
2707       * Generally uses mysql_query().  If you want to use
2708       * mysql_unbuffered_query() set the "result_buffering" option to 0 using
2709       * setOptions().  This option was added in Release 1.7.0.
2710       *
2711       * @param string  the SQL query string
2712       *
2713       * @return mixed  + a PHP result resrouce for successful SELECT queries
2714       *                + the DB_OK constant for other successful queries
2715       *                + a DB_Error object on failure
2716       *  @todo Implement mock DB_mysql::simpleQuery()
2717       */
2718      function simpleQuery($query)
2719      {
2720  //        $ismanip = DB::isManip($query);
2721  //        $this->last_query = $query;
2722  //        $query = $this->modifyQuery($query);
2723  //        if ($this->_db) {
2724  //            if (!@mysql_select_db($this->_db, $this->connection)) {
2725  //                return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
2726  //            }
2727  //        }
2728  //        if (!$this->autocommit && $ismanip) {
2729  //            if ($this->transaction_opcount == 0) {
2730  //                $result = @mysql_query('SET AUTOCOMMIT=0', $this->connection);
2731  //                $result = @mysql_query('BEGIN', $this->connection);
2732  //                if (!$result) {
2733  //                    return $this->mysqlRaiseError();
2734  //                }
2735  //            }
2736  //            $this->transaction_opcount++;
2737  //        }
2738  //        if (!$this->options['result_buffering']) {
2739  //            $result = @mysql_unbuffered_query($query, $this->connection);
2740  //        } else {
2741  //            $result = @mysql_query($query, $this->connection);
2742  //        }
2743  //        if (!$result) {
2744  //            return $this->mysqlRaiseError();
2745  //        }
2746  //        if (is_resource($result)) {
2747  //            return $result;
2748  //        }
2749          return DB_OK;
2750      }
2751  
2752      /**
2753       * Move the internal mysql result pointer to the next available result
2754       *
2755       * This method has not been implemented yet.
2756       *
2757       * @param a valid sql result resource
2758       *
2759       * @return false
2760       */
2761      function nextResult($result)
2762      {
2763          return false;
2764      }
2765  
2766      /**
2767       * Places a row from the result set into the given array
2768       *
2769       * @param resource $result    the query result resource
2770       * @param array    $arr       the referenced array to put the data in
2771       * @param int      $fetchmode how the resulting array should be indexed
2772       * @param int      $rownum    the row number to fetch (0 = first row)
2773       * @return mixed  DB_OK on success, NULL when the end of a result set is
2774       *                 reached or on failure
2775       *
2776       * @see DB_result::fetchInto()
2777       *  @todo Implement mock DB_mysql::fetchInto()
2778       */
2779      function fetchInto($result, &$arr, $fetchmode, $rownum = null)
2780      {
2781  //        if ($rownum !== null) {
2782  //            if (!@mysql_data_seek($result, $rownum)) {
2783  //                return null;
2784  //            }
2785  //        }
2786  //        if ($fetchmode & DB_FETCHMODE_ASSOC) {
2787  //            $arr = @mysql_fetch_array($result, MYSQL_ASSOC);
2788  //            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
2789  //                $arr = array_change_key_case($arr, CASE_LOWER);
2790  //            }
2791  //        } else {
2792  //            $arr = @mysql_fetch_row($result);
2793  //        }
2794  //        if (!$arr) {
2795  //            return null;
2796  //        }
2797  //        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
2798  //            /*
2799  //             * Even though this DBMS already trims output, we do this because
2800  //             * a field might have intentional whitespace at the end that
2801  //             * gets removed by DB_PORTABILITY_RTRIM under another driver.
2802  //             */
2803  //            $this->_rtrimArrayValues($arr);
2804  //        }
2805  //        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
2806  //            $this->_convertNullArrayValuesToEmpty($arr);
2807  //        }
2808          return DB_OK;
2809      }
2810  
2811      /**
2812       * Deletes the result set and frees the memory occupied by the result set
2813       *
2814       * This method is not meant to be called directly.  Use
2815       * DB_result::free() instead.  It can't be declared "protected"
2816       * because DB_result is a separate object.
2817       *
2818       * @param resource $result  PHP's query result resource
2819       *
2820       * @return bool  TRUE on success, FALSE if $result is invalid
2821       *
2822       * @see DB_result::free()
2823       *  @todo Implement mock DB_mysql::freeResult()
2824       */
2825      function freeResult($result)
2826      {
2827  //        return @mysql_free_result($result);
2828      }
2829  
2830  
2831      /**
2832       * Gets the number of columns in a result set
2833       *
2834       * This method is not meant to be called directly.  Use
2835       * DB_result::numCols() instead.  It can't be declared "protected"
2836       * because DB_result is a separate object.
2837       *
2838       * @param resource $result  PHP's query result resource
2839       *
2840       * @return int  the number of columns.  A DB_Error object on failure.
2841       *
2842       * @see DB_result::numCols()
2843       *  @todo Implement mock DB_mysql::numCols()
2844       */
2845      function numCols($result)
2846      {
2847  //        $cols = @mysql_num_fields($result);
2848  //        if (!$cols) {
2849  //            return $this->mysqlRaiseError();
2850  //        }
2851  //        return $cols;
2852      }
2853  
2854      /**
2855       * Gets the number of rows in a result set
2856       *
2857       * This method is not meant to be called directly.  Use
2858       * DB_result::numRows() instead.  It can't be declared "protected"
2859       * because DB_result is a separate object.
2860       *
2861       * @param resource $result  PHP's query result resource
2862       *
2863       * @return int  the number of rows.  A DB_Error object on failure.
2864       *
2865       * @see DB_result::numRows()
2866       *  @todo Implement mock DB_mysql::numRows()
2867       */
2868      function numRows($result)
2869      {
2870  //        $rows = @mysql_num_rows($result);
2871  //        if ($rows === null) {
2872  //            return $this->mysqlRaiseError();
2873  //        }
2874  //        return $rows;
2875      }
2876  
2877      /**
2878       * Enables or disables automatic commits
2879       *
2880       * @param bool $onoff  true turns it on, false turns it off
2881       *
2882       * @return int  DB_OK on success.  A DB_Error object if the driver
2883       *               doesn't support auto-committing transactions.
2884       *  @todo Implement mock DB_mysql::autoCommit()
2885       */
2886      function autoCommit($onoff = false)
2887      {
2888  //        // XXX if $this->transaction_opcount > 0, we should probably
2889  //        // issue a warning here.
2890  //        $this->autocommit = $onoff ? true : false;
2891          return DB_OK;
2892      }
2893  
2894      /**
2895       * Commits the current transaction
2896       *
2897       * @return int  DB_OK on success.  A DB_Error object on failure.
2898       *  @todo Implement mock DB_mysql::committ()
2899       */
2900      function commit()
2901      {
2902  //        if ($this->transaction_opcount > 0) {
2903  //            if ($this->_db) {
2904  //                if (!@mysql_select_db($this->_db, $this->connection)) {
2905  //                    return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
2906  //                }
2907  //            }
2908  //            $result = @mysql_query('COMMIT', $this->connection);
2909  //            $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
2910  //            $this->transaction_opcount = 0;
2911  //            if (!$result) {
2912  //                return $this->mysqlRaiseError();
2913  //            }
2914  //        }
2915          return DB_OK;
2916      }
2917  
2918      /**
2919       * Reverts the current transaction
2920       *
2921       * @return int  DB_OK on success.  A DB_Error object on failure.
2922       *  @todo Implement mock DB_mysql::rollback()
2923       */
2924      function rollback()
2925      {
2926  //        if ($this->transaction_opcount > 0) {
2927  //            if ($this->_db) {
2928  //                if (!@mysql_select_db($this->_db, $this->connection)) {
2929  //                    return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
2930  //                }
2931  //            }
2932  //            $result = @mysql_query('ROLLBACK', $this->connection);
2933  //            $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
2934  //            $this->transaction_opcount = 0;
2935  //            if (!$result) {
2936  //                return $this->mysqlRaiseError();
2937  //            }
2938  //        }
2939          return DB_OK;
2940      }
2941  
2942      /**
2943       * Determines the number of rows affected by a data maniuplation query
2944       *
2945       * 0 is returned for queries that don't manipulate data.
2946       *
2947       * @return int  the number of rows.  A DB_Error object on failure.
2948       *  @todo Implement mock DB_mysql::affectedRows()
2949       */
2950      function affectedRows()
2951      {
2952  //        if (DB::isManip($this->last_query)) {
2953  //            return @mysql_affected_rows($this->connection);
2954  //        } else {
2955  //            return 0;
2956  //        }
2957       }
2958  
2959      /**
2960       * Returns the next free id in a sequence
2961       *
2962       * @param string  $seq_name  name of the sequence
2963       * @param boolean $ondemand  when true, the seqence is automatically
2964       *                            created if it does not exist
2965       *
2966       * @return int  the next id number in the sequence.
2967       *               A DB_Error object on failure.
2968       *
2969       * @see DB_common::nextID(), DB_common::getSequenceName(),
2970       *      DB_mysql::createSequence(), DB_mysql::dropSequence()
2971       *  @todo Implement mock DB_mysql::nextId()
2972       */
2973      function nextId($seq_name, $ondemand = true)
2974      {
2975  //        $seqname = $this->getSequenceName($seq_name);
2976  //        do {
2977  //            $repeat = 0;
2978  //            $this->pushErrorHandling(PEAR_ERROR_RETURN);
2979  //            $result = $this->query("UPDATE ${seqname} ".
2980  //                                   'SET id=LAST_INSERT_ID(id+1)');
2981  //            $this->popErrorHandling();
2982  //            if ($result === DB_OK) {
2983  //                // COMMON CASE
2984  //                $id = @mysql_insert_id($this->connection);
2985  //                if ($id != 0) {
2986  //                    return $id;
2987  //                }
2988  //                // EMPTY SEQ TABLE
2989  //                // Sequence table must be empty for some reason, so fill
2990  //                // it and return 1 and obtain a user-level lock
2991  //                $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
2992  //                if (DB::isError($result)) {
2993  //                    return $this->raiseError($result);
2994  //                }
2995  //                if ($result == 0) {
2996  //                    // Failed to get the lock
2997  //                    return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
2998  //                }
2999  //
3000  //                // add the default value
3001  //                $result = $this->query("REPLACE INTO ${seqname} (id) VALUES (0)");
3002  //                if (DB::isError($result)) {
3003  //                    return $this->raiseError($result);
3004  //                }
3005  //
3006  //                // Release the lock
3007  //                $result = $this->getOne('SELECT RELEASE_LOCK('
3008  //                                        . "'${seqname}_lock')");
3009  //                if (DB::isError($result)) {
3010  //                    return $this->raiseError($result);
3011  //                }
3012  //                // We know what the result will be, so no need to try again
3013  //                return 1;
3014  //
3015  //            } elseif ($ondemand && DB::isError($result) &&
3016  //                $result->getCode() == DB_ERROR_NOSUCHTABLE)
3017  //            {
3018  //                // ONDEMAND TABLE CREATION
3019  //                $result = $this->createSequence($seq_name);
3020  //                if (DB::isError($result)) {
3021  //                    return $this->raiseError($result);
3022  //                } else {
3023  //                    $repeat = 1;
3024  //                }
3025  //
3026  //            } elseif (DB::isError($result) &&
3027  //                      $result->getCode() == DB_ERROR_ALREADY_EXISTS)
3028  //            {
3029  //                // BACKWARDS COMPAT
3030  //                // see _BCsequence() comment
3031  //                $result = $this->_BCsequence($seqname);
3032  //                if (DB::isError($result)) {
3033  //                    return $this->raiseError($result);
3034  //                }
3035  //                $repeat = 1;
3036  //            }
3037  //        } while ($repeat);
3038  //
3039  //        return $this->raiseError($result);
3040      }
3041  
3042      /**
3043       * Creates a new sequence
3044       *
3045       * @param string $seq_name  name of the new sequence
3046       *
3047       * @return int  DB_OK on success.  A DB_Error object on failure.
3048       *
3049       * @see DB_common::createSequence(), DB_common::getSequenceName(),
3050       *      DB_mysql::nextID(), DB_mysql::dropSequence()
3051       *  @todo Implement mock DB_mysql::createSequence()
3052       */
3053      function createSequence($seq_name)
3054      {
3055  //        $seqname = $this->getSequenceName($seq_name);
3056  //        $res = $this->query('CREATE TABLE ' . $seqname
3057  //                            . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'
3058  //                            . ' PRIMARY KEY(id))');
3059  //        if (DB::isError($res)) {
3060  //            return $res;
3061  //        }
3062  //        // insert yields value 1, nextId call will generate ID 2
3063  //        $res = $this->query("INSERT INTO ${seqname} (id) VALUES (0)");
3064  //        if (DB::isError($res)) {
3065  //            return $res;
3066  //        }
3067  //        // so reset to zero
3068  //        return $this->query("UPDATE ${seqname} SET id = 0");
3069      }
3070  
3071      /**
3072       * Deletes a sequence
3073       *
3074       * @param string $seq_name  name of the sequence to be deleted
3075       *
3076       * @return int  DB_OK on success.  A DB_Error object on failure.
3077       *
3078       * @see DB_common::dropSequence(), DB_common::getSequenceName(),
3079       *      DB_mysql::nextID(), DB_mysql::createSequence()
3080       *  @todo Implement mock DB_mysql::dropSequence()
3081       */
3082      function dropSequence($seq_name)
3083      {
3084  //        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
3085      }
3086  
3087      /**
3088       * Backwards compatibility with old sequence emulation implementation
3089       * (clean up the dupes)
3090       *
3091       * @param string $seqname  the sequence name to clean up
3092       *
3093       * @return bool  true on success.  A DB_Error object on failure.
3094       *  @todo Implement mock DB_mysql::_BCsequence()
3095       */
3096      private function _BCsequence($seqname)
3097      {
3098  //        // Obtain a user-level lock... this will release any previous
3099  //        // application locks, but unlike LOCK TABLES, it does not abort
3100  //        // the current transaction and is much less frequently used.
3101  //        $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
3102  //        if (DB::isError($result)) {
3103  //            return $result;
3104  //        }
3105  //        if ($result == 0) {
3106  //            // Failed to get the lock, can't do the conversion, bail
3107  //            // with a DB_ERROR_NOT_LOCKED error
3108  //            return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
3109  //        }
3110  //
3111  //        $highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}");
3112  //        if (DB::isError($highest_id)) {
3113  //            return $highest_id;
3114  //        }
3115  //        // This should kill all rows except the highest
3116  //        // We should probably do something if $highest_id isn't
3117  //        // numeric, but I'm at a loss as how to handle that...
3118  //        $result = $this->query('DELETE FROM ' . $seqname
3119  //                               . " WHERE id <> $highest_id");
3120  //        if (DB::isError($result)) {
3121  //            return $result;
3122  //        }
3123  //
3124  //        // If another thread has been waiting for this lock,
3125  //        // it will go thru the above procedure, but will have no
3126  //        // real effect
3127  //        $result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
3128  //        if (DB::isError($result)) {
3129  //            return $result;
3130  //        }
3131          return true;
3132      }
3133  
3134      /**
3135       * Quotes a string so it can be safely used as a table or column name
3136       *
3137       * MySQL can't handle the backtick character (<kbd>`</kbd>) in
3138       * table or column names.
3139       *
3140       * @param string $str  identifier name to be quoted
3141       * @return string  quoted identifier string
3142       * @see DB_common::quoteIdentifier()
3143       * @access private
3144       */
3145      function quoteIdentifier($str)
3146      {
3147          return '`' . $str . '`';
3148      }
3149  
3150      /**
3151       * Escapes a string according to the current DBMS's standards
3152       *
3153       * @param string $str  the string to be escaped
3154       * @return string  the escaped string
3155       * @see DB_common::quoteSmart()
3156       *  @todo Implement mock DB_mysql::escapeSimple()
3157       */
3158      function escapeSimple($str)
3159      {
3160  //        if (function_exists('mysql_real_escape_string')) {
3161  //            return @mysql_real_escape_string($str, $this->connection);
3162  //        } else {
3163  //            return @mysql_escape_string($str);
3164  //        }
3165      }
3166  
3167      /**
3168       * Changes a query string for various DBMS specific reasons
3169       *
3170       * This little hack lets you know how many rows were deleted
3171       * when running a "DELETE FROM table" query.  Only implemented
3172       * if the DB_PORTABILITY_DELETE_COUNT portability option is on.
3173       *
3174       * @param string $query  the query string to modify
3175       * @return string  the modified query string
3176       * @see DB_common::setOption()
3177       *  @todo Implement mock DB_mysql::modifyQuery()
3178       */
3179      protected function modifyQuery($query)
3180      {
3181  //        if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) {
3182  //            // "DELETE FROM table" gives 0 affected rows in MySQL.
3183  //            // This little hack lets you know how many rows were deleted.
3184  //            if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
3185  //                $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
3186  //                                      'DELETE FROM \1 WHERE 1=1', $query);
3187  //            }
3188  //        }
3189  //        return $query;
3190      }
3191  
3192      /**
3193       * Adds LIMIT clauses to a query string according to current DBMS standards
3194       *
3195       * @param string $query   the query to modify
3196       * @param int    $from    the row to start to fetching (0 = the first row)
3197       * @param int    $count   the numbers of rows to fetch
3198       * @param mixed  $params  array, string or numeric data to be used in
3199       *                         execution of the statement.  Quantity of items
3200       *                         passed must match quantity of placeholders in
3201       *                         query:  meaning 1 placeholder for non-array
3202       *                         parameters or 1 placeholder per array element.
3203       * @return string  the query string with LIMIT clauses added
3204       *  @todo Implement mock DB_mysql::modifyLimitQuery()
3205       */
3206      protected function modifyLimitQuery($query, $from, $count, $params = array())
3207      {
3208  //        if (DB::isManip($query)) {
3209  //            return $query . " LIMIT $count";
3210  //        } else {
3211  //            return $query . " LIMIT $from, $count";
3212  //        }
3213      }
3214  
3215      /**
3216       * Produces a DB_Error object regarding the current problem
3217       *
3218       * @param int $errno  if the error is being manually raised pass a
3219       *                     DB_ERROR* constant here.  If this isn't passed
3220       *                     the error information gathered from the DBMS.
3221       *
3222       * @return object  the DB_Error object
3223       * @see DB_common::raiseError(),
3224       *      DB_mysql::errorNative(), DB_common::errorCode()
3225       *  @todo Implement mock DB_mysql::mysqlRaiseError()
3226       */
3227      function mysqlRaiseError($errno = null)
3228      {
3229  //        if ($errno === null) {
3230  //            if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
3231  //                $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT;
3232  //                $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL;
3233  //                $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT;
3234  //            } else {
3235  //                // Doing this in case mode changes during runtime.
3236  //                $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS;
3237  //                $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT;
3238  //                $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS;
3239  //            }
3240  //            $errno = $this->errorCode(mysql_errno($this->connection));
3241  //        }
3242  //        return $this->raiseError($errno, null, null, null,
3243  //                                 @mysql_errno($this->connection) . ' ** ' .
3244  //                                 @mysql_error($this->connection));
3245      }
3246  
3247      /**
3248       * Gets the DBMS' native error code produced by the last query
3249       *
3250       * @return int  the DBMS' error code
3251       *  @todo Implement mock DB_mysql::errorNative()
3252       */
3253      function errorNative()
3254      {
3255  //        return @mysql_errno($this->connection);
3256      }
3257  
3258      /**
3259       * Returns information about a table or a result set
3260       *
3261       * @param object|string  $result  DB_result object from a query or a
3262       *                                 string containing the name of a table.
3263       *                                 While this also accepts a query result
3264       *                                 resource identifier, this behavior is
3265       *                                 deprecated.
3266       * @param int            $mode    a valid tableInfo mode
3267       *
3268       * @return array  an associative array with the information requested.
3269       *                 A DB_Error object on failure.
3270       *
3271       * @see DB_common::tableInfo()
3272       *  @todo Implement mock DB_mysql::tableInfo()
3273       */
3274      function tableInfo($result, $mode = null)
3275      {
3276          // We only support the default mode
3277          PHPUnit2_Framework_Assert::assertNull($mode);
3278  
3279          // We only support table name as first argument
3280          PHPUnit2_Framework_Assert::assertTrue(is_string($result));
3281  
3282          // Look up table name in the mock database
3283          foreach(self::$database as $table => $value) {
3284              if ($result == $table) {
3285                  return $value['info'];
3286              }
3287          }
3288          PHPUnit2_Framework_Assert::fail("DB_mysql::tableInfo called"
3289                                          ." with unknown table $result");
3290      }
3291  
3292      /**
3293       * Obtains the query string needed for listing a given type of objects
3294       *
3295       * @param string $type  the kind of objects you want to retrieve
3296       *
3297       * @return string  the SQL query string or null if the driver doesn't
3298       *                  support the object type requested
3299       *
3300       * @see DB_common::getListOf()
3301       */
3302      protected function getSpecialQuery($type)
3303      {
3304          switch ($type) {
3305              case 'tables':
3306                  return 'SHOW TABLES';
3307              case 'users':
3308                  return 'SELECT DISTINCT User FROM mysql.user';
3309              case 'databases':
3310                  return 'SHOW DATABASES';
3311              default:
3312                  return null;
3313          }
3314      }
3315  }
3316  
3317  // -- set Emacs parameters --
3318  // Local variables:
3319  // tab-width: 4
3320  // c-basic-offset: 4
3321  // c-hanging-comment-ender-p: nil
3322  // indent-tabs-mode: nil
3323  // End:
3324  ?>


Généré le : Sun Feb 25 20:04:38 2007 par Balluche grâce à PHPXref 0.7