[ 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/ -> common.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  // | Author: Stig Bakken <ssb@php.net>                                    |
  17  // +----------------------------------------------------------------------+
  18  //
  19  // $Id: common.php,v 1.2 2004/07/20 17:41:40 rodolphe Exp $
  20  //
  21  // Base class for DB implementations.
  22  //
  23  
  24  /**
  25   * DB_common is a base class for DB implementations, and must be
  26   * inherited by all such.
  27   */
  28  
  29  require_once DOL_DOCUMENT_ROOT."/includes/pear/PEAR.php";
  30  
  31  class DB_common extends DOLIPEAR
  32  {
  33      // {{{ properties
  34      /**
  35      * assoc of capabilities for this DB implementation
  36      * $features['limit'] =>  'emulate' => emulate with fetch row by number
  37      *                        'alter'   => alter the query
  38      *                        false     => skip rows
  39      * @var array
  40      */
  41      var $features;
  42  
  43      /**
  44      * assoc mapping native error codes to DB ones
  45      * @var array
  46      */
  47      var $errorcode_map;
  48  
  49      /**
  50      * DB type (mysql, oci8, odbc etc.)
  51      * @var string
  52      */
  53      var $type;
  54  
  55      /**
  56      * @var string
  57      */
  58      var $prepare_tokens;
  59  
  60      /**
  61      * @var string
  62      */
  63      var $prepare_types;
  64  
  65      /**
  66      * @var string
  67      */
  68      var $prepared_queries;
  69  
  70      /**
  71      * @var integer
  72      */
  73      var $prepare_maxstmt = 0;
  74  
  75      /**
  76      * @var string
  77      */
  78      var $last_query = '';
  79  
  80      /**
  81      * @var integer
  82      */
  83      var $fetchmode = DB_FETCHMODE_ORDERED;
  84  
  85      /**
  86      * @var string
  87      */
  88      var $fetchmode_object_class = 'stdClass';
  89  
  90      /**
  91      * $options["persistent"] -> boolean persistent connection true|false?
  92      * $options["optimize"] -> string 'performance' or 'portability'
  93      * $options["debug"] -> integer numeric debug level
  94      * @var array
  95      */
  96      var $options = array(
  97          'persistent' => false,
  98          'optimize' => 'performance',
  99          'debug' => 0,
 100          'seqname_format' => '%s_seq',
 101          'autofree' => false
 102      );
 103  
 104      /**
 105      * DB handle
 106      * @var resource
 107      */
 108      var $dbh;
 109  
 110      // }}}
 111      // {{{ toString()
 112      /**
 113      * String conversation
 114      *
 115      * @return string
 116      * @access private
 117      */
 118      function toString()
 119      {
 120          $info = get_class($this);
 121          $info .=  ": (phptype=" . $this->phptype .
 122                    ", dbsyntax=" . $this->dbsyntax .
 123                    ")";
 124  
 125          if ($this->connection) {
 126              $info .= " [connected]";
 127          }
 128  
 129          return $info;
 130      }
 131  
 132      // }}}
 133      // {{{ constructor
 134      /**
 135      * Constructor
 136      */
 137      function DB_common()
 138      {
 139          $this->DOLIPEAR('DB_Error');
 140          $this->features = array();
 141          $this->errorcode_map = array();
 142          $this->fetchmode = DB_FETCHMODE_ORDERED;
 143      }
 144  
 145      // }}}
 146      // {{{ quoteString()
 147  
 148      /**
 149       * Quotes a string so it can be safely used within string delimiters
 150       * in a query (preserved for compatibility issues, quote() is preffered).
 151       *
 152       * @return string quoted string
 153       * @access public
 154       * @see quote()
 155       */
 156      function quoteString($string)
 157      {
 158          $string = $this->quote($string);
 159          if ($string{0} == "'") {
 160              return substr($string, 1, -1);
 161          }
 162          return $string;
 163      }
 164  
 165      /**
 166       * Quotes a string so it can be safely used in a query. It will return
 167       * the string with single quotes around. Other backend quote styles
 168       * should override this method.
 169       *
 170       * @param string $string the input string to quote
 171       *
 172       * @return string The NULL string or the string quotes
 173       *                in magic_quote_sybase style
 174       */
 175      function quote($string)
 176      {
 177          return ($string === null) ? 'NULL' : "'".str_replace("'", "''", $string)."'";
 178      }
 179  
 180      // }}}
 181      // {{{ provides()
 182  
 183      /**
 184       * Tell whether a DB implementation or its backend extension
 185       * supports a given feature.
 186       *
 187       * @param array $feature name of the feature (see the DB class doc)
 188       * @return bool whether this DB implementation supports $feature
 189       * @access public
 190       */
 191  
 192      function provides($feature)
 193      {
 194          return $this->features[$feature];
 195      }
 196  
 197      // }}}
 198      // {{{ errorCode()
 199  
 200      /**
 201       * Map native error codes to DB's portable ones.  Requires that
 202       * the DB implementation's constructor fills in the $errorcode_map
 203       * property.
 204       *
 205       * @param mixed $nativecode the native error code, as returned by the backend
 206       * database extension (string or integer)
 207       *
 208       * @return int a portable DB error code, or FALSE if this DB
 209       * implementation has no mapping for the given error code.
 210       *
 211       * @access public
 212       */
 213  
 214      function errorCode($nativecode)
 215      {
 216          if (isset($this->errorcode_map[$nativecode])) {
 217              return $this->errorcode_map[$nativecode];
 218          }
 219          // Fall back to DB_ERROR if there was no mapping.
 220          return DB_ERROR;
 221      }
 222  
 223      // }}}
 224      // {{{ errorMessage()
 225  
 226      /**
 227       * Map a DB error code to a textual message.  This is actually
 228       * just a wrapper for DB::errorMessage().
 229       *
 230       * @param integer $dbcode the DB error code
 231       *
 232       * @return string the corresponding error message, of FALSE
 233       * if the error code was unknown
 234       *
 235       * @access public
 236       */
 237  
 238      function errorMessage($dbcode)
 239      {
 240          return DB::errorMessage($this->errorcode_map[$dbcode]);
 241      }
 242  
 243      // }}}
 244      // {{{ raiseError()
 245  
 246      /**
 247       * This method is used to communicate an error and invoke error
 248       * callbacks etc.  Basically a wrapper for PEAR::raiseError
 249       * without the message string.
 250       *
 251       * @param mixed    integer error code, or a PEAR error object (all
 252       *                 other parameters are ignored if this parameter is
 253       *                 an object
 254       *
 255       * @param int      error mode, see PEAR_Error docs
 256       *
 257       * @param mixed    If error mode is PEAR_ERROR_TRIGGER, this is the
 258       *                 error level (E_USER_NOTICE etc).  If error mode is
 259       *                 PEAR_ERROR_CALLBACK, this is the callback function,
 260       *                 either as a function name, or as an array of an
 261       *                 object and method name.  For other error modes this
 262       *                 parameter is ignored.
 263       *
 264       * @param string   Extra debug information.  Defaults to the last
 265       *                 query and native error code.
 266       *
 267       * @param mixed    Native error code, integer or string depending the
 268       *                 backend.
 269       *
 270       * @return object  a PEAR error object
 271       *
 272       * @access public
 273       * @see PEAR_Error
 274       */
 275      function &raiseError($code = DB_ERROR, $mode = null, $options = null,
 276                           $userinfo = null, $nativecode = null)
 277      {
 278          // The error is yet a DB error object
 279          if (is_object($code)) {
 280              // because we the static PEAR::raiseError, our global
 281              // handler should be used if it is set
 282              if ($mode === null && !empty($this->_default_error_mode)) {
 283                  $mode    = $this->_default_error_mode;
 284                  $options = $this->_default_error_options;
 285              }
 286              return DOLIPEAR::raiseError($code, null, $mode, $options, null, null, true);
 287          }
 288  
 289          if ($userinfo === null) {
 290              $userinfo = $this->last_query;
 291          }
 292  
 293          if ($nativecode) {
 294              $userinfo .= " [nativecode=$nativecode]";
 295          }
 296  
 297          return DOLIPEAR::raiseError(null, $code, $mode, $options, $userinfo,
 298                                    'DB_Error', true);
 299      }
 300  
 301      // }}}
 302      // {{{ setFetchMode()
 303  
 304      /**
 305       * Sets which fetch mode should be used by default on queries
 306       * on this connection.
 307       *
 308       * @param integer $fetchmode DB_FETCHMODE_ORDERED or
 309       *        DB_FETCHMODE_ASSOC, possibly bit-wise OR'ed with
 310       *        DB_FETCHMODE_FLIPPED.
 311       *
 312       * @param string $object_class The class of the object
 313       *                      to be returned by the fetch methods when
 314       *                      the DB_FETCHMODE_OBJECT mode is selected.
 315       *                      If no class is specified by default a cast
 316       *                      to object from the assoc array row will be done.
 317       *                      There is also the posibility to use and extend the
 318       *                      'DB_Row' class.
 319       *
 320       * @see DB_FETCHMODE_ORDERED
 321       * @see DB_FETCHMODE_ASSOC
 322       * @see DB_FETCHMODE_FLIPPED
 323       * @see DB_FETCHMODE_OBJECT
 324       * @see DB_Row::DB_Row()
 325       * @access public
 326       */
 327  
 328      function setFetchMode($fetchmode, $object_class = null)
 329      {
 330          switch ($fetchmode) {
 331              case DB_FETCHMODE_OBJECT:
 332                  if ($object_class) {
 333                      $this->fetchmode_object_class = $object_class;
 334                  }
 335              case DB_FETCHMODE_ORDERED:
 336              case DB_FETCHMODE_ASSOC:
 337                  $this->fetchmode = $fetchmode;
 338                  break;
 339              default:
 340                  return $this->raiseError('invalid fetchmode mode');
 341          }
 342      }
 343  
 344      // }}}
 345      // {{{ setOption()
 346      /**
 347      * set the option for the db class
 348      *
 349      * @param string $option option name
 350      * @param mixed  $value value for the option
 351      *
 352      * @return mixed DB_OK or DB_Error
 353      */
 354      function setOption($option, $value)
 355      {
 356          if (isset($this->options[$option])) {
 357              $this->options[$option] = $value;
 358              return DB_OK;
 359          }
 360          return $this->raiseError("unknown option $option");
 361      }
 362  
 363      // }}}
 364      // {{{ getOption()
 365      /**
 366      * returns the value of an option
 367      *
 368      * @param string $option option name
 369      *
 370      * @return mixed the option value
 371      */
 372      function getOption($option)
 373      {
 374          if (isset($this->options[$option])) {
 375              return $this->options[$option];
 376          }
 377          return $this->raiseError("unknown option $option");
 378      }
 379  
 380      // }}}
 381      // {{{ prepare()
 382  
 383      /**
 384      * Prepares a query for multiple execution with execute().
 385      * With some database backends, this is emulated.
 386      * prepare() requires a generic query as string like
 387      * "INSERT INTO numbers VALUES(?,?,?)". The ? are wildcards.
 388      * Types of wildcards:
 389      *   ? - a quoted scalar value, i.e. strings, integers
 390      *   & - requires a file name, the content of the file
 391      *       insert into the query (i.e. saving binary data
 392      *       in a db)
 393      *   ! - value is inserted 'as is'
 394      *
 395      * @param string the query to prepare
 396      *
 397      * @return resource handle for the query
 398      *
 399      * @access public
 400      * @see execute
 401      */
 402  
 403      function prepare($query)
 404      {
 405          $tokens = split("[\&\?\!]", $query);
 406          $token = 0;
 407          $types = array();
 408          $qlen = strlen($query);
 409          for ($i = 0; $i < $qlen; $i++) {
 410              switch ($query[$i]) {
 411                  case '?':
 412                      $types[$token++] = DB_PARAM_SCALAR;
 413                      break;
 414                  case '&':
 415                      $types[$token++] = DB_PARAM_OPAQUE;
 416                      break;
 417                  case '!':
 418                      $types[$token++] = DB_PARAM_MISC;
 419                      break;
 420              }
 421          }
 422  
 423          $this->prepare_tokens[] = &$tokens;
 424          end($this->prepare_tokens);
 425  
 426          $k = key($this->prepare_tokens);
 427          $this->prepare_types[$k] = $types;
 428          $this->prepared_queries[$k] = &$query;
 429  
 430          return $k;
 431      }
 432  
 433      // }}}
 434      // {{{ autoPrepare()
 435  
 436      /**
 437      * Make automaticaly an insert or update query and call prepare() with it
 438      *
 439      * @param string $table name of the table
 440      * @param array $table_fields ordered array containing the fields names
 441      * @param int $mode type of query to make (DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE)
 442      * @param string $where in case of update queries, this string will be put after the sql WHERE statement
 443      * @return resource handle for the query
 444      * @see buildManipSQL
 445      * @access public
 446      */
 447      function autoPrepare($table, $table_fields, $mode = DB_AUTOQUERY_INSERT, $where = false)
 448      {
 449          $query = $this->buildManipSQL($table, $table_fields, $mode, $where);
 450          return $this->prepare($query);
 451      }
 452  
 453      // {{{
 454      // }}} autoExecute()
 455  
 456      /**
 457      * Make automaticaly an insert or update query and call prepare() and execute() with it
 458      *
 459      * @param string $table name of the table
 460      * @param array $fields_values assoc ($key=>$value) where $key is a field name and $value its value
 461      * @param int $mode type of query to make (DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE)
 462      * @param string $where in case of update queries, this string will be put after the sql WHERE statement
 463      * @return mixed  a new DB_Result or a DB_Error when fail
 464      * @see buildManipSQL
 465      * @see autoPrepare
 466      * @access public
 467      */
 468      function autoExecute($table, $fields_values, $mode = DB_AUTOQUERY_INSERT, $where = false)
 469      {
 470          $sth = $this->autoPrepare($table, array_keys($fields_values), $mode, $where);
 471          $ret = $this->execute($sth, array_values($fields_values));
 472          $this->freePrepared($sth);
 473          return $ret;
 474  
 475      }
 476  
 477      // {{{
 478      // }}} buildManipSQL()
 479  
 480      /**
 481      * Make automaticaly an sql query for prepare()
 482      *
 483      * Example : buildManipSQL('table_sql', array('field1', 'field2', 'field3'), DB_AUTOQUERY_INSERT)
 484      *           will return the string : INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?)
 485      * NB : - This belongs more to a SQL Builder class, but this is a simple facility
 486      *      - Be carefull ! If you don't give a $where param with an UPDATE query, all
 487      *        the records of the table will be updated !
 488      *
 489      * @param string $table name of the table
 490      * @param array $table_fields ordered array containing the fields names
 491      * @param int $mode type of query to make (DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE)
 492      * @param string $where in case of update queries, this string will be put after the sql WHERE statement
 493      * @return string sql query for prepare()
 494      * @access public
 495      */
 496      function buildManipSQL($table, $table_fields, $mode, $where = false)
 497      {
 498          if (count($table_fields) == 0) {
 499              $this->raiseError(DB_ERROR_NEED_MORE_DATA);
 500          }
 501          $first = true;
 502          switch ($mode) {
 503              case DB_AUTOQUERY_INSERT:
 504                  $values = '';
 505                  $names = '';
 506                  while (list(, $value) = each($table_fields)) {
 507                      if ($first) {
 508                          $first = false;
 509                      } else {
 510                          $names .= ',';
 511                          $values .= ',';
 512                      }
 513                      $names .= $value;
 514                      $values .= '?';
 515                  }
 516                  return "INSERT INTO $table ($names) VALUES ($values)";
 517                  break;
 518              case DB_AUTOQUERY_UPDATE:
 519                  $set = '';
 520                  while (list(, $value) = each($table_fields)) {
 521                      if ($first) {
 522                          $first = false;
 523                      } else {
 524                          $set .= ',';
 525                      }
 526                      $set .= "$value = ?";
 527                  }
 528                  $sql = "UPDATE $table SET $set";
 529                  if ($where) {
 530                      $sql .= " WHERE $where";
 531                  }
 532                  return $sql;
 533                  break;
 534              default:
 535                  $this->raiseError(DB_ERROR_SYNTAX);
 536          }
 537      }
 538  
 539      // }}}
 540      // {{{ execute()
 541      /**
 542      * Executes a prepared SQL query
 543      * With execute() the generic query of prepare is
 544      * assigned with the given data array. The values
 545      * of the array inserted into the query in the same
 546      * order like the array order
 547      *
 548      * @param resource $stmt query handle from prepare()
 549      * @param array    $data numeric array containing the
 550      *                       data to insert into the query
 551      *
 552      * @return mixed  a new DB_Result or a DB_Error when fail
 553      *
 554      * @access public
 555      * @see prepare()
 556      */
 557      function &execute($stmt, $data = false)
 558      {
 559          $realquery = $this->executeEmulateQuery($stmt, $data);
 560          if (DB::isError($realquery)) {
 561              return $realquery;
 562          }
 563          $result = $this->simpleQuery($realquery);
 564  
 565          if (DB::isError($result) || $result === DB_OK) {
 566              return $result;
 567          } else {
 568              return new DB_result($this, $result);
 569          }
 570      }
 571  
 572      // }}}
 573      // {{{ executeEmulateQuery()
 574  
 575      /**
 576      * Emulates the execute statement, when not supported
 577      *
 578      * @param resource $stmt query handle from prepare()
 579      * @param array    $data numeric array containing the
 580      *                       data to insert into the query
 581      *
 582      * @return mixed a string containing the real query run when emulating
 583      * prepare/execute.  A DB error code is returned on failure.
 584      *
 585      * @access private
 586      * @see execute()
 587      */
 588  
 589      function executeEmulateQuery($stmt, $data = false)
 590      {
 591          $p = &$this->prepare_tokens;
 592  
 593          if (!isset($this->prepare_tokens[$stmt]) ||
 594              !is_array($this->prepare_tokens[$stmt]) ||
 595              !sizeof($this->prepare_tokens[$stmt]))
 596          {
 597              return $this->raiseError(DB_ERROR_INVALID);
 598          }
 599  
 600          $qq = &$this->prepare_tokens[$stmt];
 601          $qp = sizeof($qq) - 1;
 602  
 603          if ((!$data && $qp > 0) ||
 604              (!is_array($data) && $qp > 1) ||
 605              (is_array($data) && $qp > sizeof($data)))
 606          {
 607              $this->last_query = $this->prepared_queries[$stmt];
 608              return $this->raiseError(DB_ERROR_NEED_MORE_DATA);
 609          }
 610  
 611          $realquery = $qq[0];
 612          for ($i = 0; $i < $qp; $i++) {
 613              $type = $this->prepare_types[$stmt][$i];
 614              if ($type == DB_PARAM_OPAQUE) {
 615                  if (is_array($data)) {
 616                      $fp = fopen($data[$i], 'r');
 617                  } else {
 618                      $fp = fopen($data, 'r');
 619                  }
 620  
 621                  $pdata = '';
 622  
 623                  if ($fp) {
 624                      while (($buf = fread($fp, 4096)) != false) {
 625                          $pdata .= $buf;
 626                      }
 627                      fclose($fp);
 628                  }
 629              } else {
 630                  if (is_array($data)) {
 631                      $pdata = &$data[$i];
 632                  } else {
 633                      $pdata = &$data;
 634                  }
 635              }
 636  
 637              $realquery .= ($type != DB_PARAM_MISC) ? $this->quote($pdata) : $pdata;
 638              $realquery .= $qq[$i + 1];
 639          }
 640  
 641          return $realquery;
 642      }
 643  
 644      // }}}
 645      // {{{ executeMultiple()
 646  
 647      /**
 648      * This function does several execute() calls on the same
 649      * statement handle.  $data must be an array indexed numerically
 650      * from 0, one execute call is done for every "row" in the array.
 651      *
 652      * If an error occurs during execute(), executeMultiple() does not
 653      * execute the unfinished rows, but rather returns that error.
 654      *
 655      * @param resource $stmt query handle from prepare()
 656      * @param array    $data numeric array containing the
 657      *                       data to insert into the query
 658      *
 659      * @return mixed DB_OK or DB_Error
 660      *
 661      * @access public
 662      * @see prepare(), execute()
 663      */
 664  
 665      function executeMultiple( $stmt, &$data )
 666      {
 667          for($i = 0; $i < sizeof( $data ); $i++) {
 668              $res = $this->execute($stmt, $data[$i]);
 669              if (DB::isError($res)) {
 670                  return $res;
 671              }
 672          }
 673          return DB_OK;
 674      }
 675  
 676      // }}}
 677      // {{{ freePrepared()
 678  
 679      /*
 680      * Free the resource used in a prepared query
 681      *
 682      * @param $stmt The resurce returned by the prepare() function
 683      * @see prepare()
 684      */
 685      function freePrepared($stmt)
 686      {
 687          // Free the internal prepared vars

 688          if (isset($this->prepare_tokens[$stmt])) {
 689              unset($this->prepare_tokens[$stmt]);
 690              unset($this->prepare_types[$stmt]);
 691              unset($this->prepared_queries[$stmt]);
 692              return true;
 693          }
 694          return false;
 695      }
 696  
 697      // }}}
 698      // {{{ modifyQuery()
 699  
 700      /**
 701       * This method is used by backends to alter queries for various
 702       * reasons.  It is defined here to assure that all implementations
 703       * have this method defined.
 704       *
 705       * @param string $query  query to modify
 706       *
 707       * @return the new (modified) query
 708       *
 709       * @access private
 710       */
 711      function modifyQuery($query) {
 712          return $query;
 713      }
 714  
 715      // }}}
 716      // {{{ modifyLimitQuery()
 717      /**
 718      * This method is used by backends to alter limited queries
 719      *
 720      * @param string  $query query to modify
 721      * @param integer $from  the row to start to fetching
 722      * @param integer $count the numbers of rows to fetch
 723      *
 724      * @return the new (modified) query
 725      *
 726      * @access private
 727      */
 728  
 729      function modifyLimitQuery($query, $from, $count)
 730      {
 731          return $query;
 732      }
 733  
 734      // }}}
 735      // {{{ query()
 736  
 737      /**
 738       * Send a query to the database and return any results with a
 739       * DB_result object.
 740       *
 741       * @access public
 742       *
 743       * @param string $query  the SQL query or the statement to prepare
 744       * @param string $params the data to be added to the query
 745       * @return mixed a DB_result object or DB_OK on success, a DB
 746       *                error on failure
 747       *
 748       * @see DB::isError
 749       * @see DB_common::prepare
 750       * @see DB_common::execute
 751       */
 752      function &query($query, $params = array()) {
 753          if (sizeof($params) > 0) {
 754              $sth = $this->prepare($query);
 755              if (DB::isError($sth)) {
 756                  return $sth;
 757              }
 758              $ret = $this->execute($sth, $params);
 759              $this->freePrepared($sth);
 760              return $ret;
 761          } else {
 762              $result = $this->simpleQuery($query);
 763              if (DB::isError($result) || $result === DB_OK) {
 764                  return $result;
 765              } else {
 766                  return new DB_result($this, $result);
 767              }
 768          }
 769      }
 770  
 771      // }}}
 772      // {{{ limitQuery()
 773      /**
 774      * Generates a limited query
 775      *
 776      * @param string  $query query
 777      * @param integer $from  the row to start to fetching
 778      * @param integer $count the numbers of rows to fetch
 779      * @param array   $params required for a statement
 780      *
 781      * @return mixed a DB_Result object, DB_OK or a DB_Error
 782      *
 783      * @access public
 784      */
 785      function &limitQuery($query, $from, $count, $params = array())
 786      {
 787          $query  = $this->modifyLimitQuery($query, $from, $count);
 788          $result = $this->query($query, $params);
 789          if (get_class($result) == 'db_result') {
 790              $result->setOption('limit_from', $from);
 791              $result->setOption('limit_count', $count);
 792          }
 793          return $result;
 794      }
 795  
 796      // }}}
 797      // {{{ getOne()
 798  
 799      /**
 800       * Fetch the first column of the first row of data returned from
 801       * a query.  Takes care of doing the query and freeing the results
 802       * when finished.
 803       *
 804       * @param string $query the SQL query
 805       * @param array $params if supplied, prepare/execute will be used
 806       *        with this array as execute parameters
 807       *
 808       * @return mixed DB_Error or the returned value of the query
 809       *
 810       * @access public
 811       */
 812  
 813      function &getOne($query, $params = array())
 814      {
 815          settype($params, "array");
 816          if (sizeof($params) > 0) {
 817              $sth = $this->prepare($query);
 818              if (DB::isError($sth)) {
 819                  return $sth;
 820              }
 821              $res = $this->execute($sth, $params);
 822              $this->freePrepared($sth);
 823          } else {
 824              $res = $this->query($query);
 825          }
 826  
 827          if (DB::isError($res)) {
 828              return $res;
 829          }
 830  
 831          $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED);
 832  
 833          $res->free();
 834  
 835          if ($err !== DB_OK) {
 836              return $err;
 837          }
 838  
 839          return $row[0];
 840      }
 841  
 842      // }}}
 843      // {{{ getRow()
 844  
 845      /**
 846       * Fetch the first row of data returned from a query.  Takes care
 847       * of doing the query and freeing the results when finished.
 848       *
 849       * @param string $query the SQL query
 850       * @param integer $fetchmode the fetch mode to use
 851       * @param array $params array if supplied, prepare/execute will be used
 852       *        with this array as execute parameters
 853       * @access public
 854       * @return array the first row of results as an array indexed from
 855       * 0, or a DB error code.
 856       */
 857  
 858      function &getRow($query,
 859                       $params = null,
 860                       $fetchmode = DB_FETCHMODE_DEFAULT)
 861      {
 862          // compat check, the params and fetchmode parameters used to
 863          // have the opposite order
 864          if (!is_array($params)) {
 865              if (is_array($fetchmode)) {
 866                  $tmp = $params;
 867                  $params = $fetchmode;
 868                  $fetchmode = $tmp;
 869              } elseif ($params !== null) {
 870                  $fetchmode = $params;
 871                  $params = null;
 872              }
 873          }
 874          $params = (empty($params)) ? array() : $params;
 875          $fetchmode = (empty($fetchmode)) ? DB_FETCHMODE_DEFAULT : $fetchmode;
 876          settype($params, 'array');
 877          if (sizeof($params) > 0) {
 878              $sth = $this->prepare($query);
 879              if (DB::isError($sth)) {
 880                  return $sth;
 881              }
 882              $res = $this->execute($sth, $params);
 883              $this->freePrepared($sth);
 884          } else {
 885              $res = $this->query($query);
 886          }
 887  
 888          if (DB::isError($res)) {
 889              return $res;
 890          }
 891  
 892          $err = $res->fetchInto($row, $fetchmode);
 893  
 894          $res->free();
 895  
 896          if ($err !== DB_OK) {
 897              return $err;
 898          }
 899  
 900          return $row;
 901      }
 902  
 903      // }}}
 904      // {{{ getCol()
 905  
 906      /**
 907       * Fetch a single column from a result set and return it as an
 908       * indexed array.
 909       *
 910       * @param string $query the SQL query
 911       *
 912       * @param mixed $col which column to return (integer [column number,
 913       * starting at 0] or string [column name])
 914       *
 915       * @param array $params array if supplied, prepare/execute will be used
 916       *        with this array as execute parameters
 917       * @access public
 918       *
 919       * @return array an indexed array with the data from the first
 920       * row at index 0, or a DB error code.
 921       */
 922  
 923      function &getCol($query, $col = 0, $params = array())
 924      {
 925          settype($params, "array");
 926          if (sizeof($params) > 0) {
 927              $sth = $this->prepare($query);
 928  
 929              if (DB::isError($sth)) {
 930                  return $sth;
 931              }
 932  
 933              $res = $this->execute($sth, $params);
 934              $this->freePrepared($sth);
 935          } else {
 936              $res = $this->query($query);
 937          }
 938  
 939          if (DB::isError($res)) {
 940              return $res;
 941          }
 942  
 943          $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC;
 944          $ret = array();
 945  
 946          while (is_array($row = $res->fetchRow($fetchmode))) {
 947              $ret[] = $row[$col];
 948          }
 949  
 950          $res->free();
 951  
 952          if (DB::isError($row)) {
 953              $ret = $row;
 954          }
 955  
 956          return $ret;
 957      }
 958  
 959      // }}}
 960      // {{{ getAssoc()
 961  
 962      /**
 963       * Fetch the entire result set of a query and return it as an
 964       * associative array using the first column as the key.
 965       *
 966       * If the result set contains more than two columns, the value
 967       * will be an array of the values from column 2-n.  If the result
 968       * set contains only two columns, the returned value will be a
 969       * scalar with the value of the second column (unless forced to an
 970       * array with the $force_array parameter).  A DB error code is
 971       * returned on errors.  If the result set contains fewer than two
 972       * columns, a DB_ERROR_TRUNCATED error is returned.
 973       *
 974       * For example, if the table "mytable" contains:
 975       *
 976       *  ID      TEXT       DATE
 977       * --------------------------------
 978       *  1       'one'      944679408
 979       *  2       'two'      944679408
 980       *  3       'three'    944679408
 981       *
 982       * Then the call getAssoc('SELECT id,text FROM mytable') returns:
 983       *   array(
 984       *     '1' => 'one',
 985       *     '2' => 'two',
 986       *     '3' => 'three',
 987       *   )
 988       *
 989       * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
 990       *   array(
 991       *     '1' => array('one', '944679408'),
 992       *     '2' => array('two', '944679408'),
 993       *     '3' => array('three', '944679408')
 994       *   )
 995       *
 996       * If the more than one row occurs with the same value in the
 997       * first column, the last row overwrites all previous ones by
 998       * default.  Use the $group parameter if you don't want to
 999       * overwrite like this.  Example:
1000       *
1001       * getAssoc('SELECT category,id,name FROM mytable', false, null,
1002       *          DB_FETCHMODE_ASSOC, true) returns:
1003       *   array(
1004       *     '1' => array(array('id' => '4', 'name' => 'number four'),
1005       *                  array('id' => '6', 'name' => 'number six')
1006       *            ),
1007       *     '9' => array(array('id' => '4', 'name' => 'number four'),
1008       *                  array('id' => '6', 'name' => 'number six')
1009       *            )
1010       *   )
1011       *
1012       * Keep in mind that database functions in PHP usually return string
1013       * values for results regardless of the database's internal type.
1014       *
1015       * @param string $query the SQL query
1016       *
1017       * @param boolean $force_array used only when the query returns
1018       * exactly two columns.  If true, the values of the returned array
1019       * will be one-element arrays instead of scalars.
1020       *
1021       * @param array $params array if supplied, prepare/execute will be used
1022       *        with this array as execute parameters
1023       *
1024       * @param boolean $group if true, the values of the returned array
1025       *                       is wrapped in another array.  If the same
1026       *                       key value (in the first column) repeats
1027       *                       itself, the values will be appended to
1028       *                       this array instead of overwriting the
1029       *                       existing values.
1030       *
1031       * @access public
1032       *
1033       * @return array associative array with results from the query.
1034       */
1035  
1036      function &getAssoc($query, $force_array = false, $params = array(),
1037                         $fetchmode = DB_FETCHMODE_ORDERED, $group = false)
1038      {
1039          settype($params, "array");
1040          if (sizeof($params) > 0) {
1041              $sth = $this->prepare($query);
1042  
1043              if (DB::isError($sth)) {
1044                  return $sth;
1045              }
1046  
1047              $res = $this->execute($sth, $params);
1048              $this->freePrepared($sth);
1049          } else {
1050              $res = $this->query($query);
1051          }
1052  
1053          if (DB::isError($res)) {
1054              return $res;
1055          }
1056  
1057          $cols = $res->numCols();
1058  
1059          if ($cols < 2) {
1060              return $this->raiseError(DB_ERROR_TRUNCATED);
1061          }
1062  
1063          $results = array();
1064  
1065          if ($cols > 2 || $force_array) {
1066              // return array values
1067              // XXX this part can be optimized
1068              if ($fetchmode == DB_FETCHMODE_ASSOC) {
1069                  while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) {
1070                      reset($row);
1071                      $key = current($row);
1072                      unset($row[key($row)]);
1073                      if ($group) {
1074                          $results[$key][] = $row;
1075                      } else {
1076                          $results[$key] = $row;
1077                      }
1078                  }
1079              } else {
1080                  while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
1081                      // we shift away the first element to get
1082                      // indices running from 0 again
1083                      $key = array_shift($row);
1084                      if ($group) {
1085                          $results[$key][] = $row;
1086                      } else {
1087                          $results[$key] = $row;
1088                      }
1089                  }
1090              }
1091              if (DB::isError($row)) {
1092                  $results = $row;
1093              }
1094          } else {
1095              // return scalar values
1096              while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
1097                  if ($group) {
1098                      $results[$row[0]][] = $row[1];
1099                  } else {
1100                      $results[$row[0]] = $row[1];
1101                  }
1102              }
1103              if (DB::isError($row)) {
1104                  $results = $row;
1105              }
1106          }
1107  
1108          $res->free();
1109  
1110          return $results;
1111      }
1112  
1113      // }}}
1114      // {{{ getAll()
1115  
1116      /**
1117       * Fetch all the rows returned from a query.
1118       *
1119       * @param string $query the SQL query
1120       *
1121       * @param array $params array if supplied, prepare/execute will be used
1122       *        with this array as execute parameters
1123       * @param integer $fetchmode the fetch mode to use
1124       *
1125       * @access public
1126       * @return array an nested array, or a DB error
1127       */
1128  
1129      function &getAll($query,
1130                       $params = null,
1131                       $fetchmode = DB_FETCHMODE_DEFAULT)
1132      {
1133          // compat check, the params and fetchmode parameters used to
1134          // have the opposite order
1135          if (!is_array($params)) {
1136              if (is_array($fetchmode)) {
1137                  $tmp = $params;
1138                  $params = $fetchmode;
1139                  $fetchmode = $tmp;
1140              } elseif ($params !== null) {
1141                  $fetchmode = $params;
1142                  $params = null;
1143              }
1144          }
1145          $params = (empty($params)) ? array() : $params;
1146          $fetchmode = (empty($fetchmode)) ? DB_FETCHMODE_DEFAULT : $fetchmode;
1147          settype($params, "array");
1148          if (sizeof($params) > 0) {
1149              $sth = $this->prepare($query);
1150  
1151              if (DB::isError($sth)) {
1152                  return $sth;
1153              }
1154  
1155              $res = $this->execute($sth, $params);
1156              $this->freePrepared($sth);
1157          } else {
1158              $res = $this->query($query);
1159          }
1160  
1161          if (DB::isError($res)) {
1162              return $res;
1163          }
1164  
1165          $results = array();
1166          while (DB_OK === $res->fetchInto($row, $fetchmode)) {
1167              if ($fetchmode & DB_FETCHMODE_FLIPPED) {
1168                  foreach ($row as $key => $val) {
1169                      $results[$key][] = $val;
1170                  }
1171              } else {
1172                  $results[] = $row;
1173              }
1174          }
1175  
1176          $res->free();
1177  
1178          if (DB::isError($row)) {
1179              return $this->raiseError($row);
1180          }
1181          return $results;
1182      }
1183  
1184      // }}}
1185      // {{{ autoCommit()
1186      /**
1187      * enable automatic Commit
1188      *
1189      * @param boolean $onoff
1190      * @return mixed DB_Error
1191      *
1192      * @access public
1193      */
1194      function autoCommit($onoff=false)
1195      {
1196          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1197      }
1198  
1199      // }}}
1200      // {{{ commit()
1201      /**
1202      * starts a Commit
1203      *
1204      * @return mixed DB_Error
1205      *
1206      * @access public
1207      */
1208      function commit()
1209      {
1210          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1211      }
1212  
1213      // }}}
1214      // {{{ rollback()
1215      /**
1216      * starts a rollback
1217      *
1218      * @return mixed DB_Error
1219      *
1220      * @access public
1221      */
1222      function rollback()
1223      {
1224          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1225      }
1226  
1227      // }}}
1228      // {{{ numRows()
1229      /**
1230      * returns the number of rows in a result object
1231      *
1232      * @param object DB_Result the result object to check
1233      *
1234      * @return mixed DB_Error or the number of rows
1235      *
1236      * @access public
1237      */
1238      function numRows($result)
1239      {
1240          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1241      }
1242  
1243      // }}}
1244      // {{{ affectedRows()
1245      /**
1246      * returns the affected rows of a query
1247      *
1248      * @return mixed DB_Error or number of rows
1249      *
1250      * @access public
1251      */
1252      function affectedRows()
1253      {
1254          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1255      }
1256  
1257      // }}}
1258      // {{{ errorNative()
1259      /**
1260      * returns an errormessage, provides by the database
1261      *
1262      * @return mixed DB_Error or message
1263      *
1264      * @access public
1265      */
1266      function errorNative()
1267      {
1268          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1269      }
1270  
1271      // }}}
1272      // {{{ nextId()
1273      /**
1274      * returns the next free id of a sequence
1275      *
1276      * @param string  $seq_name name of the sequence
1277      * @param boolean $ondemand when true the seqence is
1278      *                          automatic created, if it
1279      *                          not exists
1280      *
1281      * @return mixed DB_Error or id
1282      */
1283      function nextId($seq_name, $ondemand = true)
1284      {
1285          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1286      }
1287  
1288      // }}}
1289      // {{{ createSequence()
1290      /**
1291      * creates a new sequence
1292      *
1293      * @param string $seq_name name of the new sequence
1294      *
1295      * @return mixed DB_Error
1296      *
1297      * @access public
1298      */
1299      function createSequence($seq_name)
1300      {
1301          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1302      }
1303  
1304      // }}}
1305      // {{{ dropSequence()
1306      /**
1307      * deletes a sequence
1308      *
1309      * @param string $seq_name name of the sequence
1310      *
1311      * @return mixed DB_Error
1312      *
1313      * @access public
1314      */
1315      function dropSequence($seq_name)
1316      {
1317          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1318      }
1319  
1320      // }}}
1321      // {{{ tableInfo()
1322      /**
1323      * returns meta data about the result set
1324      *
1325      * @param object DB_Result $result the result object to analyse
1326      * @param mixed $mode depends on implementation
1327      *
1328      * @return mixed DB_Error
1329      *
1330      * @access public
1331      */
1332      function tableInfo($result, $mode = null)
1333      {
1334          return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1335      }
1336  
1337      // }}}
1338      // {{{ getTables()
1339      /**
1340      * @deprecated
1341      */
1342      function getTables()
1343      {
1344          return $this->getListOf('tables');
1345      }
1346  
1347      // }}}
1348      // {{{ getListOf()
1349      /**
1350      * list internal DB info
1351      * valid values for $type are db dependent,
1352      * often: databases, users, view, functions
1353      *
1354      * @param string $type type of requested info
1355      *
1356      * @return mixed DB_Error or the requested data
1357      *
1358      * @access public
1359      */
1360      function getListOf($type)
1361      {
1362          $sql = $this->getSpecialQuery($type);
1363          if ($sql === null) {                                // No support
1364              return $this->raiseError(DB_ERROR_UNSUPPORTED);
1365          } elseif (is_int($sql) || DB::isError($sql)) {      // Previous error
1366              return $this->raiseError($sql);
1367          } elseif (is_array($sql)) {                         // Already the result
1368              return $sql;
1369          }
1370          return $this->getCol($sql);                         // Launch this query
1371      }
1372      // }}}
1373      // {{{ getSequenceName()
1374  
1375      function getSequenceName($sqn)
1376      {
1377          return sprintf($this->getOption("seqname_format"),
1378                         preg_replace('/[^a-z0-9_]/i', '_', $sqn));
1379      }
1380  
1381      // }}}
1382  }
1383  
1384  // Used by many drivers
1385  if (!function_exists('array_change_key_case')) {
1386      define('CASE_UPPER', 1);
1387      define('CASE_LOWER', 0);
1388      function &array_change_key_case(&$array, $case) {
1389          $casefunc = ($case == CASE_LOWER) ? 'strtolower' : 'strtoupper';
1390          $ret = array();
1391          foreach ($array as $key => $value) {
1392              $ret[$casefunc($key)] = $value;
1393          }
1394          return $ret;
1395      }
1396  }
1397  
1398  ?>


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