[ Index ]
 

Code source de Dolibarr 2.0.1

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/htdocs/includes/pear/ -> DB.php (source)

   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
   3  // +----------------------------------------------------------------------+
   4  // | PHP Version 4                                                        |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 1997-2003 The PHP Group                                |
   7  // +----------------------------------------------------------------------+
   8  // | This source file is subject to version 2.02 of the PHP license,      |
   9  // | that is bundled with this package in the file LICENSE, and is        |
  10  // | available at through the world-wide-web at                           |
  11  // | http://www.php.net/license/2_02.txt.                                 |
  12  // | If you did not receive a copy of the PHP license and are unable to   |
  13  // | obtain it through the world-wide-web, please send a note to          |
  14  // | license@php.net so we can mail you a copy immediately.               |
  15  // +----------------------------------------------------------------------+
  16  // | Authors: Stig Bakken <ssb@php.net>                                   |
  17  // |          Tomas V.V.Cox <cox@idecnet.com>                             |
  18  // +----------------------------------------------------------------------+
  19  //
  20  // $Id: DB.php,v 1.2 2004/07/20 17:41:40 rodolphe Exp $
  21  //
  22  // Database independent query interface.
  23  //
  24  
  25  //require_once "PEAR.php";
  26  require_once DOL_DOCUMENT_ROOT."/includes/pear/PEAR.php";
  27  // {{{ constants
  28  // {{{ error codes
  29  /*
  30   * The method mapErrorCode in each DB_dbtype implementation maps
  31   * native error codes to one of these.
  32   *
  33   * If you add an error code here, make sure you also add a textual
  34   * version of it in DB::errorMessage().
  35   */
  36  
  37  define("DB_OK",                         1);
  38  define("DB_ERROR",                     -1);
  39  define("DB_ERROR_SYNTAX",              -2);
  40  define("DB_ERROR_CONSTRAINT",          -3);
  41  define("DB_ERROR_NOT_FOUND",           -4);
  42  define("DB_ERROR_ALREADY_EXISTS",      -5);
  43  define("DB_ERROR_UNSUPPORTED",         -6);
  44  define("DB_ERROR_MISMATCH",            -7);
  45  define("DB_ERROR_INVALID",             -8);
  46  define("DB_ERROR_NOT_CAPABLE",         -9);
  47  define("DB_ERROR_TRUNCATED",          -10);
  48  define("DB_ERROR_INVALID_NUMBER",     -11);
  49  define("DB_ERROR_INVALID_DATE",       -12);
  50  define("DB_ERROR_DIVZERO",            -13);
  51  define("DB_ERROR_NODBSELECTED",       -14);
  52  define("DB_ERROR_CANNOT_CREATE",      -15);
  53  define("DB_ERROR_CANNOT_DELETE",      -16);
  54  define("DB_ERROR_CANNOT_DROP",        -17);
  55  define("DB_ERROR_NOSUCHTABLE",        -18);
  56  define("DB_ERROR_NOSUCHFIELD",        -19);
  57  define("DB_ERROR_NEED_MORE_DATA",     -20);
  58  define("DB_ERROR_NOT_LOCKED",         -21);
  59  define("DB_ERROR_VALUE_COUNT_ON_ROW", -22);
  60  define("DB_ERROR_INVALID_DSN",        -23);
  61  define("DB_ERROR_CONNECT_FAILED",     -24);
  62  define("DB_ERROR_EXTENSION_NOT_FOUND",-25);
  63  define("DB_ERROR_ACCESS_VIOLATION",   -26);
  64  define("DB_ERROR_NOSUCHDB",           -27);
  65  
  66  // }}}
  67  // {{{ warning codes
  68  /*
  69   * Warnings are not detected as errors by DB::isError(), and are not
  70   * fatal.  You can detect whether an error is in fact a warning with
  71   * DB::isWarning().
  72   *
  73   * @deprecated
  74   */
  75  
  76  define('DB_WARNING',           -1000);
  77  define('DB_WARNING_READ_ONLY', -1001);
  78  
  79  // }}}
  80  // {{{ prepared statement-related
  81  /*
  82   * These constants are used when storing information about prepared
  83   * statements (using the "prepare" method in DB_dbtype).
  84   *
  85   * The prepare/execute model in DB is mostly borrowed from the ODBC
  86   * extension, in a query the "?" character means a scalar parameter.
  87   * There are two extensions though, a "&" character means an opaque
  88   * parameter.  An opaque parameter is simply a file name, the real
  89   * data are in that file (useful for putting uploaded files into your
  90   * database and such). The "!" char means a parameter that must be
  91   * left as it is.
  92   * They modify the quote behavoir:
  93   * DB_PARAM_SCALAR (?) => 'original string quoted'
  94   * DB_PARAM_OPAQUE (&) => 'string from file quoted'
  95   * DB_PARAM_MISC   (!) => original string
  96   */
  97  
  98  define('DB_PARAM_SCALAR', 1);
  99  define('DB_PARAM_OPAQUE', 2);
 100  define('DB_PARAM_MISC',   3);
 101  
 102  // }}}
 103  // {{{ binary data-related
 104  /*
 105   * These constants define different ways of returning binary data
 106   * from queries.  Again, this model has been borrowed from the ODBC
 107   * extension.
 108   *
 109   * DB_BINMODE_PASSTHRU sends the data directly through to the browser
 110   * when data is fetched from the database.
 111   * DB_BINMODE_RETURN lets you return data as usual.
 112   * DB_BINMODE_CONVERT returns data as well, only it is converted to
 113   * hex format, for example the string "123" would become "313233".
 114   */
 115  
 116  define('DB_BINMODE_PASSTHRU', 1);
 117  define('DB_BINMODE_RETURN',   2);
 118  define('DB_BINMODE_CONVERT',  3);
 119  
 120  // }}}
 121  // {{{ fetch modes
 122  /**
 123   * This is a special constant that tells DB the user hasn't specified
 124   * any particular get mode, so the default should be used.
 125   */
 126  
 127  define('DB_FETCHMODE_DEFAULT', 0);
 128  
 129  /**
 130   * Column data indexed by numbers, ordered from 0 and up
 131   */
 132  
 133  define('DB_FETCHMODE_ORDERED', 1);
 134  
 135  /**
 136   * Column data indexed by column names
 137   */
 138  
 139  define('DB_FETCHMODE_ASSOC', 2);
 140  
 141  /**
 142   * Column data as object properties
 143   */
 144  
 145  define('DB_FETCHMODE_OBJECT', 3);
 146  
 147  /**
 148   * For multi-dimensional results: normally the first level of arrays
 149   * is the row number, and the second level indexed by column number or name.
 150   * DB_FETCHMODE_FLIPPED switches this order, so the first level of arrays
 151   * is the column name, and the second level the row number.
 152   */
 153  
 154  define('DB_FETCHMODE_FLIPPED', 4);
 155  
 156  /* for compatibility */
 157  
 158  define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
 159  define('DB_GETMODE_ASSOC',   DB_FETCHMODE_ASSOC);
 160  define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED);
 161  
 162  // }}}
 163  // {{{ tableInfo() && autoPrepare()-related
 164  /**
 165   * these are constants for the tableInfo-function
 166   * they are bitwised or'ed. so if there are more constants to be defined
 167   * in the future, adjust DB_TABLEINFO_FULL accordingly
 168   */
 169  
 170  define('DB_TABLEINFO_ORDER', 1);
 171  define('DB_TABLEINFO_ORDERTABLE', 2);
 172  define('DB_TABLEINFO_FULL', 3);
 173  
 174  /*
 175   * Used by autoPrepare()
 176   */
 177  define('DB_AUTOQUERY_INSERT', 1);
 178  define('DB_AUTOQUERY_UPDATE', 2);
 179  
 180  // }}}
 181  // }}}
 182  
 183  // {{{ class DB
 184  /**
 185   * The main "DB" class is simply a container class with some static
 186   * methods for creating DB objects as well as some utility functions
 187   * common to all parts of DB.
 188   *
 189   * The object model of DB is as follows (indentation means inheritance):
 190   *
 191   * DB           The main DB class.  This is simply a utility class
 192   *              with some "static" methods for creating DB objects as
 193   *              well as common utility functions for other DB classes.
 194   *
 195   * DB_common    The base for each DB implementation.  Provides default
 196   * |            implementations (in OO lingo virtual methods) for
 197   * |            the actual DB implementations as well as a bunch of
 198   * |            query utility functions.
 199   * |
 200   * +-DB_mysql   The DB implementation for MySQL.  Inherits DB_common.
 201   *              When calling DB::factory or DB::connect for MySQL
 202   *              connections, the object returned is an instance of this
 203   *              class.
 204   *
 205   * @package  DB
 206   * @author   Stig Bakken <ssb@php.net>
 207   * @since    PHP 4.0
 208   */
 209  
 210  class DB
 211  {
 212      // {{{ &factory()
 213      /**
 214       * Create a new DB connection object for the specified database
 215       * type
 216       *
 217       * @param string $type database type, for example "mysql"
 218       *
 219       * @return mixed a newly created DB object, or a DB error code on
 220       * error
 221       *
 222       * access public
 223       */
 224  
 225      function &factory($type)
 226      {
 227          include_once(DOL_DOCUMENT_ROOT."/includes/pear/DB/$type}.php");
 228  
 229          $classname = "DB_$type}";
 230  
 231          if (!class_exists($classname)) {
 232              return DOLIPEAR::raiseError(null, DB_ERROR_NOT_FOUND,
 233                                      null, null, null, 'DB_Error', true);
 234          }
 235  
 236          @$obj =& new $classname;
 237  
 238          return $obj;
 239      }
 240  
 241      // }}}
 242      // {{{ &connect()
 243      /**
 244       * Create a new DB connection object and connect to the specified
 245       * database
 246       *
 247       * @param mixed $dsn "data source name", see the DB::parseDSN
 248       * method for a description of the dsn format.  Can also be
 249       * specified as an array of the format returned by DB::parseDSN.
 250       *
 251       * @param mixed $options An associative array of option names and
 252       * their values.  For backwards compatibility, this parameter may
 253       * also be a boolean that tells whether the connection should be
 254       * persistent.  See DB_common::setOption for more information on
 255       * connection options.
 256       *
 257       * @return mixed a newly created DB connection object, or a DB
 258       * error object on error
 259       *
 260       * @see DB::parseDSN
 261       * @see DB::isError
 262       * @see DB_common::setOption
 263       */
 264      function &connect($dsn, $options = false)
 265      {
 266          if (is_array($dsn)) {
 267              $dsninfo = $dsn;
 268          } else {
 269              $dsninfo = DB::parseDSN($dsn);
 270          }
 271          $type = $dsninfo["phptype"];
 272  
 273          if (is_array($options) && isset($options["debug"]) &&
 274              $options["debug"] >= 2) {
 275              // expose php errors with sufficient debug level
 276              include_once DOL_DOCUMENT_ROOT."/includes/pear/DB/$type}.php";
 277          } else {
 278              include_once DOL_DOCUMENT_ROOT."/includes/pear/DB/$type}.php";
 279          }
 280  
 281          $classname = "DB_$type}";
 282          if (!class_exists($classname)) {
 283              return DOLIPEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
 284                                      "Unable to include the DB/{$type}.php file for `$dsn'",
 285                                      'DB_Error', true);
 286          }
 287  
 288          @$obj =& new $classname;
 289  
 290          if (is_array($options)) {
 291              foreach ($options as $option => $value) {
 292                  $test = $obj->setOption($option, $value);
 293                  if (DB::isError($test)) {
 294                      return $test;
 295                  }
 296              }
 297          } else {
 298              $obj->setOption('persistent', $options);
 299          }
 300          $err = $obj->connect($dsninfo, $obj->getOption('persistent'));
 301          if (DB::isError($err)) {
 302              $err->addUserInfo($dsn);
 303              return $err;
 304          }
 305  
 306          return $obj;
 307      }
 308  
 309      // }}}
 310      // {{{ apiVersion()
 311      /**
 312       * Return the DB API version
 313       *
 314       * @return int the DB API version number
 315       *
 316       * @access public
 317       */
 318      function apiVersion()
 319      {
 320          return 2;
 321      }
 322  
 323      // }}}
 324      // {{{ isError()
 325      /**
 326       * Tell whether a result code from a DB method is an error
 327       *
 328       * @param int $value result code
 329       *
 330       * @return bool whether $value is an error
 331       *
 332       * @access public
 333       */
 334      function isError($value)
 335      {
 336          return (is_object($value) &&
 337                  (get_class($value) == 'db_error' ||
 338                   is_subclass_of($value, 'db_error')));
 339      }
 340  
 341      // }}}
 342      // {{{ isConnection()
 343      /**
 344       * Tell whether a value is a DB connection
 345       *
 346       * @param mixed $value value to test
 347       *
 348       * @return bool whether $value is a DB connection
 349       *
 350       * @access public
 351       */
 352      function isConnection($value)
 353      {
 354          return (is_object($value) &&
 355                  is_subclass_of($value, 'db_common') &&
 356                  method_exists($value, 'simpleQuery'));
 357      }
 358  
 359      // }}}
 360      // {{{ isManip()
 361      /**
 362       * Tell whether a query is a data manipulation query (insert,
 363       * update or delete) or a data definition query (create, drop,
 364       * alter, grant, revoke).
 365       *
 366       * @access public
 367       *
 368       * @param string $query the query
 369       *
 370       * @return boolean whether $query is a data manipulation query
 371       */
 372      function isManip($query)
 373      {
 374          $manips = 'INSERT|UPDATE|DELETE|'.'REPLACE|CREATE|DROP|'.
 375                    'ALTER|GRANT|REVOKE|'.'LOCK|UNLOCK';
 376          if (preg_match('/^\s*"?('.$manips.')\s+/i', $query)) {
 377              return true;
 378          }
 379          return false;
 380      }
 381  
 382      // }}}
 383      // {{{ errorMessage()
 384      /**
 385       * Return a textual error message for a DB error code
 386       *
 387       * @param integer $value error code
 388       *
 389       * @return string error message, or false if the error code was
 390       * not recognized
 391       */
 392      function errorMessage($value)
 393      {
 394          static $errorMessages;
 395          if (!isset($errorMessages)) {
 396              $errorMessages = array(
 397                  DB_ERROR                    => 'unknown error',
 398                  DB_ERROR_ALREADY_EXISTS     => 'already exists',
 399                  DB_ERROR_CANNOT_CREATE      => 'can not create',
 400                  DB_ERROR_CANNOT_DELETE      => 'can not delete',
 401                  DB_ERROR_CANNOT_DROP        => 'can not drop',
 402                  DB_ERROR_CONSTRAINT         => 'constraint violation',
 403                  DB_ERROR_DIVZERO            => 'division by zero',
 404                  DB_ERROR_INVALID            => 'invalid',
 405                  DB_ERROR_INVALID_DATE       => 'invalid date or time',
 406                  DB_ERROR_INVALID_NUMBER     => 'invalid number',
 407                  DB_ERROR_MISMATCH           => 'mismatch',
 408                  DB_ERROR_NODBSELECTED       => 'no database selected',
 409                  DB_ERROR_NOSUCHFIELD        => 'no such field',
 410                  DB_ERROR_NOSUCHTABLE        => 'no such table',
 411                  DB_ERROR_NOT_CAPABLE        => 'DB backend not capable',
 412                  DB_ERROR_NOT_FOUND          => 'not found',
 413                  DB_ERROR_NOT_LOCKED         => 'not locked',
 414                  DB_ERROR_SYNTAX             => 'syntax error',
 415                  DB_ERROR_UNSUPPORTED        => 'not supported',
 416                  DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
 417                  DB_ERROR_INVALID_DSN        => 'invalid DSN',
 418                  DB_ERROR_CONNECT_FAILED     => 'connect failed',
 419                  DB_OK                       => 'no error',
 420                  DB_WARNING                  => 'unknown warning',
 421                  DB_WARNING_READ_ONLY        => 'read only',
 422                  DB_ERROR_NEED_MORE_DATA     => 'insufficient data supplied',
 423                  DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
 424                  DB_ERROR_NOSUCHDB           => 'no such database',
 425                  DB_ERROR_ACCESS_VIOLATION   => 'insufficient permissions',
 426                  DB_ERROR_TRUNCATED          => 'truncated'
 427              );
 428          }
 429  
 430          if (DB::isError($value)) {
 431              $value = $value->getCode();
 432          }
 433  
 434          return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[DB_ERROR];
 435      }
 436  
 437      // }}}
 438      // {{{ parseDSN()
 439      /**
 440       * Parse a data source name
 441       *
 442       * A array with the following keys will be returned:
 443       *  phptype: Database backend used in PHP (mysql, odbc etc.)
 444       *  dbsyntax: Database used with regards to SQL syntax etc.
 445       *  protocol: Communication protocol to use (tcp, unix etc.)
 446       *  hostspec: Host specification (hostname[:port])
 447       *  database: Database to use on the DBMS server
 448       *  username: User name for login
 449       *  password: Password for login
 450       *
 451       * The format of the supplied DSN is in its fullest form:
 452       *
 453       *  phptype(dbsyntax)://username:password@protocol+hostspec/database
 454       *
 455       * Most variations are allowed:
 456       *
 457       *  phptype://username:password@protocol+hostspec:110//usr/db_file.db
 458       *  phptype://username:password@hostspec/database_name
 459       *  phptype://username:password@hostspec
 460       *  phptype://username@hostspec
 461       *  phptype://hostspec/database
 462       *  phptype://hostspec
 463       *  phptype(dbsyntax)
 464       *  phptype
 465       *
 466       * @param string $dsn Data Source Name to be parsed
 467       *
 468       * @return array an associative array
 469       *
 470       * @author Tomas V.V.Cox <cox@idecnet.com>
 471       */
 472      function parseDSN($dsn)
 473      {
 474          if (is_array($dsn)) {
 475              return $dsn;
 476          }
 477  
 478          $parsed = array(
 479              'phptype'  => false,
 480              'dbsyntax' => false,
 481              'username' => false,
 482              'password' => false,
 483              'protocol' => false,
 484              'hostspec' => false,
 485              'port'     => false,
 486              'socket'   => false,
 487              'database' => false
 488          );
 489  
 490          // Find phptype and dbsyntax
 491          if (($pos = strpos($dsn, '://')) !== false) {
 492              $str = substr($dsn, 0, $pos);
 493              $dsn = substr($dsn, $pos + 3);
 494          } else {
 495              $str = $dsn;
 496              $dsn = NULL;
 497          }
 498  
 499          // Get phptype and dbsyntax
 500          // $str => phptype(dbsyntax)
 501          if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
 502              $parsed['phptype']  = $arr[1];
 503              $parsed['dbsyntax'] = (empty($arr[2])) ? $arr[1] : $arr[2];
 504          } else {
 505              $parsed['phptype']  = $str;
 506              $parsed['dbsyntax'] = $str;
 507          }
 508  
 509          if (empty($dsn)) {
 510              return $parsed;
 511          }
 512  
 513          // Get (if found): username and password
 514          // $dsn => username:password@protocol+hostspec/database
 515          if (($at = strrpos($dsn,'@')) !== false) {
 516              $str = substr($dsn, 0, $at);
 517              $dsn = substr($dsn, $at + 1);
 518              if (($pos = strpos($str, ':')) !== false) {
 519                  $parsed['username'] = rawurldecode(substr($str, 0, $pos));
 520                  $parsed['password'] = rawurldecode(substr($str, $pos + 1));
 521              } else {
 522                  $parsed['username'] = rawurldecode($str);
 523              }
 524          }
 525  
 526          // Find protocol and hostspec
 527  
 528          // $dsn => proto(proto_opts)/database
 529          if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
 530              $proto       = $match[1];
 531              $proto_opts  = (!empty($match[2])) ? $match[2] : false;
 532              $dsn         = $match[3];
 533  
 534          // $dsn => protocol+hostspec/database (old format)
 535          } else {
 536              if (strpos($dsn, '+') !== false) {
 537                  list($proto, $dsn) = explode('+', $dsn, 2);
 538              }
 539              if (strpos($dsn, '/') !== false) {
 540                  list($proto_opts, $dsn) = explode('/', $dsn, 2);
 541              } else {
 542                  $proto_opts = $dsn;
 543                  $dsn = null;
 544              }
 545          }
 546  
 547          // process the different protocol options
 548          $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
 549          $proto_opts = rawurldecode($proto_opts);
 550          if ($parsed['protocol'] == 'tcp') {
 551              if (strpos($proto_opts, ':') !== false) {
 552                  list($parsed['hostspec'], $parsed['port']) = explode(':', $proto_opts);
 553              } else {
 554                  $parsed['hostspec'] = $proto_opts;
 555              }
 556          } elseif ($parsed['protocol'] == 'unix') {
 557              $parsed['socket'] = $proto_opts;
 558          }
 559  
 560          // Get dabase if any
 561          // $dsn => database
 562          if (!empty($dsn)) {
 563              // /database
 564              if (($pos = strpos($dsn, '?')) === false) {
 565                  $parsed['database'] = $dsn;
 566              // /database?param1=value1&param2=value2
 567              } else {
 568                  $parsed['database'] = substr($dsn, 0, $pos);
 569                  $dsn = substr($dsn, $pos + 1);
 570                  if (strpos($dsn, '&') !== false) {
 571                      $opts = explode('&', $dsn);
 572                  } else { // database?param1=value1
 573                      $opts = array($dsn);
 574                  }
 575                  foreach ($opts as $opt) {
 576                      list($key, $value) = explode('=', $opt);
 577                      if (!isset($parsed[$key])) { // don't allow params overwrite
 578                          $parsed[$key] = rawurldecode($value);
 579                      }
 580                  }
 581              }
 582          }
 583  
 584          return $parsed;
 585      }
 586  
 587      // }}}
 588      // {{{ assertExtension()
 589      /**
 590       * Load a PHP database extension if it is not loaded already.
 591       *
 592       * @access public
 593       *
 594       * @param string $name the base name of the extension (without the .so or
 595       *                     .dll suffix)
 596       *
 597       * @return boolean true if the extension was already or successfully
 598       *                 loaded, false if it could not be loaded
 599       */
 600      function assertExtension($name)
 601      {
 602          if (!extension_loaded($name)) {
 603              $dlext = OS_WINDOWS ? '.dll' : '.so';
 604              $dlprefix = OS_WINDOWS ? 'php_' : '';
 605              @dl($dlprefix . $name . $dlext);
 606              return extension_loaded($name);
 607          }
 608          return true;
 609      }
 610      // }}}
 611  }
 612  // }}}
 613  
 614  // {{{ class DB_Error
 615  /**
 616   * DB_Error implements a class for reporting portable database error
 617   * messages.
 618   *
 619   * @package  DB
 620   * @author Stig Bakken <ssb@php.net>
 621   */
 622  class DB_Error extends DOLIPEAR_Error
 623  {
 624      // {{{ constructor
 625      /**
 626       * DB_Error constructor.
 627       *
 628       * @param mixed   $code   DB error code, or string with error message.
 629       * @param integer $mode   what "error mode" to operate in
 630       * @param integer $level  what error level to use for $mode & PEAR_ERROR_TRIGGER
 631       * @param mixed   $debuginfo  additional debug info, such as the last query
 632       *
 633       * @access public
 634       *
 635       * @see PEAR_Error
 636       */
 637  
 638      function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN,
 639                $level = E_USER_NOTICE, $debuginfo = null)
 640      {
 641          if (is_int($code)) {
 642              $this->DOLIPEAR_Error('DB Error: ' . DB::errorMessage($code), $code, $mode, $level, $debuginfo);
 643          } else {
 644              $this->DOLIPEAR_Error("DB Error: $code", DB_ERROR, $mode, $level, $debuginfo);
 645          }
 646      }
 647      // }}}
 648  }
 649  // }}}
 650  
 651  // {{{ class DB_Result
 652  /**
 653   * This class implements a wrapper for a DB result set.
 654   * A new instance of this class will be returned by the DB implementation
 655   * after processing a query that returns data.
 656   *
 657   * @package  DB
 658   * @author Stig Bakken <ssb@php.net>
 659   */
 660  
 661  class DB_result
 662  {
 663      // {{{ properties
 664  
 665      var $dbh;
 666      var $result;
 667      var $row_counter = null;
 668      /**
 669      * for limit queries, the row to start fetching
 670      * @var integer
 671      */
 672      var $limit_from  = null;
 673  
 674      /**
 675      * for limit queries, the number of rows to fetch
 676      * @var integer
 677      */
 678      var $limit_count = null;
 679  
 680      // }}}
 681      // {{{ constructor
 682      /**
 683       * DB_result constructor.
 684       * @param resource &$dbh   DB object reference
 685       * @param resource $result  result resource id

 686       * @param array    $options assoc array with optional result options
 687       */
 688  
 689      function DB_result(&$dbh, $result, $options = array())
 690      {
 691          $this->dbh = &$dbh;
 692          $this->result = $result;
 693          foreach ($options as $key => $value) {
 694              $this->setOption($key, $value);
 695          }
 696          $this->limit_type  = $dbh->features['limit'];
 697          $this->autofree    = $dbh->options['autofree'];
 698          $this->fetchmode   = $dbh->fetchmode;
 699          $this->fetchmode_object_class = $dbh->fetchmode_object_class;
 700      }
 701  
 702      function setOption($key, $value = null)
 703      {
 704          switch ($key) {
 705              case 'limit_from':
 706                  $this->limit_from = $value; break;
 707              case 'limit_count';
 708                  $this->limit_count = $value; break;
 709          }
 710      }
 711  
 712      // }}}
 713      // {{{ fetchRow()
 714      /**
 715       * Fetch and return a row of data (it uses driver->fetchInto for that)
 716       * @param int $fetchmode format of fetched row
 717       * @param int $rownum    the row number to fetch
 718       *
 719       * @return  array a row of data, NULL on no more rows or PEAR_Error on error
 720       *
 721       * @access public
 722       */
 723      function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
 724      {
 725          if ($fetchmode === DB_FETCHMODE_DEFAULT) {
 726              $fetchmode = $this->fetchmode;
 727          }
 728          if ($fetchmode === DB_FETCHMODE_OBJECT) {
 729              $fetchmode = DB_FETCHMODE_ASSOC;
 730              $object_class = $this->fetchmode_object_class;
 731          }
 732          if ($this->limit_from !== null) {
 733              if ($this->row_counter === null) {
 734                  $this->row_counter = $this->limit_from;
 735                  // Skip rows
 736                  if ($this->limit_type == false) {
 737                      $i = 0;
 738                      while ($i++ < $this->limit_from) {
 739                          $this->dbh->fetchInto($this->result, $arr, $fetchmode);
 740                      }
 741                  }
 742              }
 743              if ($this->row_counter >= (
 744                      $this->limit_from + $this->limit_count))
 745              {
 746                  if ($this->autofree) {
 747                      $this->free();
 748                  }
 749                  return null;
 750              }
 751              if ($this->limit_type == 'emulate') {
 752                  $rownum = $this->row_counter;
 753              }
 754              $this->row_counter++;
 755          }
 756          $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
 757          if ($res === DB_OK) {
 758              if (isset($object_class)) {
 759                  // default mode specified in DB_common::fetchmode_object_class property
 760                  if ($object_class == 'stdClass') {
 761                      $arr = (object) $arr;
 762                  } else {
 763                      $arr = &new $object_class($arr);
 764                  }
 765              }
 766              return $arr;
 767          }
 768          if ($res == null && $this->autofree) {
 769              $this->free();
 770          }
 771          return $res;
 772      }
 773  
 774      // }}}
 775      // {{{ fetchInto()
 776      /**
 777       * Fetch a row of data into an existing variable.
 778       *
 779       * @param  mixed   &$arr     reference to data containing the row
 780       * @param  integer $fetchmod format of fetched row
 781       * @param  integer $rownum   the row number to fetch
 782       *
 783       * @return  mixed  DB_OK on success, NULL on no more rows or
 784       *                 a DB_Error object on error
 785       *
 786       * @access public
 787       */
 788      function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
 789      {
 790          if ($fetchmode === DB_FETCHMODE_DEFAULT) {
 791              $fetchmode = $this->fetchmode;
 792          }
 793          if ($fetchmode === DB_FETCHMODE_OBJECT) {
 794              $fetchmode = DB_FETCHMODE_ASSOC;
 795              $object_class = $this->fetchmode_object_class;
 796          }
 797          if ($this->limit_from !== null) {
 798              if ($this->row_counter === null) {
 799                  $this->row_counter = $this->limit_from;
 800                  // Skip rows
 801                  if ($this->limit_type == false) {
 802                      $i = 0;
 803                      while ($i++ < $this->limit_from) {
 804                          $this->dbh->fetchInto($this->result, $arr, $fetchmode);
 805                      }
 806                  }
 807              }
 808              if ($this->row_counter >= (
 809                      $this->limit_from + $this->limit_count))
 810              {
 811                  if ($this->autofree) {
 812                      $this->free();
 813                  }
 814                  return null;
 815              }
 816              if ($this->limit_type == 'emulate') {
 817                  $rownum = $this->row_counter;
 818              }
 819  
 820              $this->row_counter++;
 821          }
 822          $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
 823          if ($res === DB_OK) {
 824              if (isset($object_class)) {
 825                  // default mode specified in DB_common::fetchmode_object_class property
 826                  if ($object_class == 'stdClass') {
 827                      $arr = (object) $arr;
 828                  } else {
 829                      $arr = new $object_class($arr);
 830                  }
 831              }
 832              return DB_OK;
 833          }
 834          if ($res == null && $this->autofree) {
 835              $this->free();
 836          }
 837          return $res;
 838      }
 839  
 840      // }}}
 841      // {{{ numCols()
 842      /**
 843       * Get the the number of columns in a result set.
 844       *
 845       * @return int the number of columns, or a DB error
 846       *
 847       * @access public
 848       */
 849      function numCols()
 850      {
 851          return $this->dbh->numCols($this->result);
 852      }
 853  
 854      // }}}
 855      // {{{ numRows()
 856      /**
 857       * Get the number of rows in a result set.
 858       *
 859       * @return int the number of rows, or a DB error
 860       *
 861       * @access public
 862       */
 863      function numRows()
 864      {
 865          return $this->dbh->numRows($this->result);
 866      }
 867  
 868      // }}}
 869      // {{{ nextResult()
 870      /**
 871       * Get the next result if a batch of queries was executed.
 872       *
 873       * @return bool true if a new result is available or false if not.
 874       *
 875       * @access public
 876       */
 877      function nextResult()
 878      {
 879          return $this->dbh->nextResult($this->result);
 880      }
 881  
 882      // }}}
 883      // {{{ free()
 884      /**
 885       * Frees the resources allocated for this result set.
 886       * @return  int error code
 887       *
 888       * @access public
 889       */
 890      function free()
 891      {
 892          $err = $this->dbh->freeResult($this->result);
 893          if(DB::isError($err)) {
 894              return $err;
 895          }
 896          $this->result = false;
 897          return true;
 898      }
 899  
 900      // }}}
 901      // {{{ tableInfo()
 902      /**
 903      * @deprecated
 904      */
 905      function tableInfo($mode = null)
 906      {
 907          return $this->dbh->tableInfo($this->result, $mode);
 908      }
 909  
 910      // }}}
 911      // {{{ getRowCounter()
 912      /**
 913      * returns the actual row number
 914      * @return integer
 915      */
 916      function getRowCounter()
 917      {
 918          return $this->row_counter;
 919      }
 920      // }}}
 921  }
 922  // }}}
 923  
 924  // {{{ class DB_Row
 925  /**
 926  * Pear DB Row Object
 927  * @see DB_common::setFetchMode()
 928  */
 929  class DB_row
 930  {
 931      // {{{ constructor
 932      /**
 933      * constructor
 934      *
 935      * @param resource row data as array
 936      */
 937      function DB_row(&$arr)
 938      {
 939          for (reset($arr); $key = key($arr); next($arr)) {
 940              $this->$key = &$arr[$key];
 941          }
 942      }
 943  
 944      // }}}
 945  }
 946  // }}}
 947  
 948  ?>


Généré le : Mon Nov 26 12:29:37 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics