[ Index ]
 

Code source de PHP PEAR 1.4.5

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

title

Body

[fermer]

/MDB/ -> mysql.php (source)

   1  <?php
   2  // vim: set et ts=4 sw=4 fdm=marker:
   3  // +----------------------------------------------------------------------+
   4  // | PHP Version 4                                                        |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
   7  // | Stig. S. Bakken, Lukas Smith                                         |
   8  // | All rights reserved.                                                 |
   9  // +----------------------------------------------------------------------+
  10  // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  11  // | API as well as database abstraction for PHP applications.            |
  12  // | This LICENSE is in the BSD license style.                            |
  13  // |                                                                      |
  14  // | Redistribution and use in source and binary forms, with or without   |
  15  // | modification, are permitted provided that the following conditions   |
  16  // | are met:                                                             |
  17  // |                                                                      |
  18  // | Redistributions of source code must retain the above copyright       |
  19  // | notice, this list of conditions and the following disclaimer.        |
  20  // |                                                                      |
  21  // | Redistributions in binary form must reproduce the above copyright    |
  22  // | notice, this list of conditions and the following disclaimer in the  |
  23  // | documentation and/or other materials provided with the distribution. |
  24  // |                                                                      |
  25  // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  26  // | Lukas Smith nor the names of his contributors may be used to endorse |
  27  // | or promote products derived from this software without specific prior|
  28  // | written permission.                                                  |
  29  // |                                                                      |
  30  // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  31  // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  32  // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  33  // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  34  // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  35  // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  36  // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  37  // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  38  // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  39  // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  40  // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  41  // | POSSIBILITY OF SUCH DAMAGE.                                          |
  42  // +----------------------------------------------------------------------+
  43  // | Author: Lukas Smith <smith@backendmedia.com>                         |
  44  // +----------------------------------------------------------------------+
  45  //
  46  // $Id: mysql.php,v 1.80.4.18 2004/04/22 11:31:56 lsmith Exp $
  47  //
  48  
  49  require_once ('MDB/Common.php');
  50  
  51  /**
  52   * MDB MySQL driver
  53   *
  54   * Notes:
  55   * - The decimal type fields are emulated with integer fields.
  56   *
  57   * @package MDB
  58   * @category Database
  59   * @author  Lukas Smith <smith@backendmedia.com>
  60   */
  61  class MDB_mysql extends MDB_Common
  62  {
  63      // {{{ properties
  64  
  65      var $connection = 0;
  66      var $connected_host;
  67      var $connected_user;
  68      var $connected_password;
  69      var $connected_port;
  70      var $opened_persistent = '';
  71  
  72      var $escape_quotes = "\\";
  73      var $decimal_factor = 1.0;
  74  
  75      var $highest_fetched_row = array();
  76      var $columns = array();
  77  
  78      // MySQL specific class variable
  79      var $default_table_type = '';
  80      var $fixed_float = 0;
  81      var $dummy_primary_key = 'dummy_primary_key';
  82  
  83      // }}}
  84      // {{{ constructor
  85  
  86      /**
  87      * Constructor
  88      */
  89      function MDB_mysql()
  90      {
  91          $this->MDB_Common();
  92          $this->phptype = 'mysql';
  93          $this->dbsyntax = 'mysql';
  94  
  95          $this->supported['Sequences'] = 1;
  96          $this->supported['Indexes'] = 1;
  97          $this->supported['AffectedRows'] = 1;
  98          $this->supported['Summaryfunctions'] = 1;
  99          $this->supported['OrderByText'] = 1;
 100          $this->supported['CurrId'] = 1;
 101          $this->supported['SelectRowRanges'] = 1;
 102          $this->supported['LOBs'] = 1;
 103          $this->supported['Replace'] = 1;
 104          $this->supported['SubSelects'] = 0;
 105          $this->supported['Transactions'] = 0;
 106  
 107          $this->decimal_factor = pow(10.0, $this->decimal_places);
 108  
 109          $this->options['DefaultTableType'] = FALSE;
 110          $this->options['fixed_float'] = FALSE;
 111  
 112          $this->errorcode_map = array(
 113              1004 => MDB_ERROR_CANNOT_CREATE,
 114              1005 => MDB_ERROR_CANNOT_CREATE,
 115              1006 => MDB_ERROR_CANNOT_CREATE,
 116              1007 => MDB_ERROR_ALREADY_EXISTS,
 117              1008 => MDB_ERROR_CANNOT_DROP,
 118              1022 => MDB_ERROR_ALREADY_EXISTS,
 119              1046 => MDB_ERROR_NODBSELECTED,
 120              1050 => MDB_ERROR_ALREADY_EXISTS,
 121              1051 => MDB_ERROR_NOSUCHTABLE,
 122              1054 => MDB_ERROR_NOSUCHFIELD,
 123              1062 => MDB_ERROR_ALREADY_EXISTS,
 124              1064 => MDB_ERROR_SYNTAX,
 125              1100 => MDB_ERROR_NOT_LOCKED,
 126              1136 => MDB_ERROR_VALUE_COUNT_ON_ROW,
 127              1146 => MDB_ERROR_NOSUCHTABLE,
 128              1048 => MDB_ERROR_CONSTRAINT,
 129              1213 => MDB_ERROR_DEADLOCK,
 130              1216 => MDB_ERROR_CONSTRAINT,
 131          );
 132      }
 133  
 134      // }}}
 135      // {{{ errorNative()
 136  
 137      /**
 138       * Get the native error code of the last error (if any) that
 139       * occured on the current connection.
 140       *
 141       * @access public
 142       *
 143       * @return int native MySQL error code
 144       */
 145      function errorNative()
 146      {
 147          return(@mysql_errno($this->connection));
 148      }
 149  
 150      // }}}
 151      // {{{ mysqlRaiseError()
 152  
 153      /**
 154       * This method is used to communicate an error and invoke error
 155       * callbacks etc.  Basically a wrapper for MDB::raiseError
 156       * that checks for native error msgs.
 157       *
 158       * @param integer $errno error code
 159       * @param string  $message userinfo message
 160       * @return object a PEAR error object
 161       * @access public
 162       * @see PEAR_Error
 163       */
 164      function mysqlRaiseError($errno = NULL, $message = NULL)
 165      {
 166          if ($errno == NULL) {
 167              if ($this->connection) {
 168                  $errno = @mysql_errno($this->connection);
 169              } else {
 170                  $errno = @mysql_errno();
 171              }
 172          }
 173          if ($this->connection) {
 174              $error = @mysql_errno($this->connection);
 175          } else {
 176              $error = @mysql_error();
 177          }
 178          return($this->raiseError($this->errorCode($errno), NULL, NULL,
 179              $message, $error));
 180      }
 181  
 182      // }}}
 183      // {{{ quoteIdentifier()
 184  
 185      /**
 186       * Quote a string so it can be safely used as a table or column name
 187       *
 188       * Quoting style depends on which database driver is being used.
 189       *
 190       * MySQL can't handle the backtick character (<kbd>`</kbd>) in
 191       * table or column names.
 192       *
 193       * @param string $str  identifier name to be quoted
 194       *
 195       * @return string  quoted identifier string
 196       *
 197       * @access public
 198       * @internal
 199       */
 200      function quoteIdentifier($str)
 201      {
 202          return '`' . $str . '`';
 203      }
 204  
 205      // }}}
 206      // {{{ autoCommit()
 207  
 208      /**
 209       * Define whether database changes done on the database be automatically
 210       * committed. This function may also implicitly start or end a transaction.
 211       *
 212       * @param boolean $auto_commit    flag that indicates whether the database
 213       *                                changes should be committed right after
 214       *                                executing every query statement. If this
 215       *                                argument is 0 a transaction implicitly
 216       *                                started. Otherwise, if a transaction is
 217       *                                in progress it is ended by committing any
 218       *                                database changes that were pending.
 219       *
 220       * @access public
 221       *
 222       * @return mixed MDB_OK on success, a MDB error on failure
 223       */
 224      function autoCommit($auto_commit)
 225      {
 226          $this->debug("AutoCommit: ".($auto_commit ? "On" : "Off"));
 227          if (!isset($this->supported['Transactions'])) {
 228              return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
 229                  'Auto-commit transactions: transactions are not in use'));
 230          }
 231          if ($this->auto_commit == $auto_commit) {
 232              return(MDB_OK);
 233          }
 234          if ($this->connection) {
 235              if ($auto_commit) {
 236                  $result = $this->query('COMMIT');
 237                  if (MDB::isError($result)) {
 238                      return($result);
 239                  }
 240                  $result = $this->query('SET AUTOCOMMIT = 1');
 241                  if (MDB::isError($result)) {
 242                      return($result);
 243                  }
 244              } else {
 245                  $result = $this->query('SET AUTOCOMMIT = 0');
 246                  if (MDB::isError($result)) {
 247                      return($result);
 248                  }
 249              }
 250          }
 251          $this->auto_commit = $auto_commit;
 252          $this->in_transaction = !$auto_commit;
 253          return(MDB_OK);
 254      }
 255  
 256      // }}}
 257      // {{{ commit()
 258  
 259      /**
 260       * Commit the database changes done during a transaction that is in
 261       * progress. This function may only be called when auto-committing is
 262       * disabled, otherwise it will fail. Therefore, a new transaction is
 263       * implicitly started after committing the pending changes.
 264       *
 265       * @access public
 266       *
 267       * @return mixed MDB_OK on success, a MDB error on failure
 268       */
 269      function commit()
 270      {
 271          $this->debug("Commit Transaction");
 272          if (!isset($this->supported['Transactions'])) {
 273              return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
 274                  'Commit transactions: transactions are not in use'));
 275          }
 276          if ($this->auto_commit) {
 277              return($this->raiseError(MDB_ERROR, NULL, NULL,
 278              'Commit transactions: transaction changes are being auto commited'));
 279          }
 280          return($this->query('COMMIT'));
 281      }
 282  
 283      // }}}
 284      // {{{ rollback()
 285  
 286      /**
 287       * Cancel any database changes done during a transaction that is in
 288       * progress. This function may only be called when auto-committing is
 289       * disabled, otherwise it will fail. Therefore, a new transaction is
 290       * implicitly started after canceling the pending changes.
 291       *
 292       * @access public
 293       *
 294       * @return mixed MDB_OK on success, a MDB error on failure
 295       */
 296      function rollback()
 297      {
 298          $this->debug("Rollback Transaction");
 299          if (!isset($this->supported['Transactions'])) {
 300              return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
 301                  'Rollback transactions: transactions are not in use'));
 302          }
 303          if ($this->auto_commit) {
 304              return($this->raiseError(MDB_ERROR, NULL, NULL,
 305                  'Rollback transactions: transactions can not be rolled back when changes are auto commited'));
 306          }
 307          return($this->query('ROLLBACK'));
 308      }
 309  
 310      // }}}
 311      // {{{ connect()
 312  
 313      /**
 314       * Connect to the database
 315       *
 316       * @return TRUE on success, MDB_Error on failure
 317       **/
 318      function connect()
 319      {
 320          $port = (isset($this->port) ? $this->port : '');
 321          if($this->connection != 0) {
 322              if (!strcmp($this->connected_host, $this->host)
 323                  && !strcmp($this->connected_user, $this->user)
 324                  && !strcmp($this->connected_password, $this->password)
 325                  && !strcmp($this->connected_port, $port)
 326                  && $this->opened_persistent == $this->options['persistent'])
 327              {
 328                  return(MDB_OK);
 329              }
 330              @mysql_close($this->connection);
 331              $this->connection = 0;
 332              $this->affected_rows = -1;
 333          }
 334  
 335          if(!PEAR::loadExtension($this->phptype)) {
 336              return(PEAR::raiseError(NULL, MDB_ERROR_NOT_FOUND,
 337                  NULL, NULL, 'extension '.$this->phptype.' is not compiled into PHP',
 338                  'MDB_Error', TRUE));
 339          }
 340          $UseTransactions = $this->getOption('UseTransactions');
 341          if(!MDB::isError($UseTransactions) && $UseTransactions) {
 342              $this->supported['Transactions'] = 1;
 343              $this->default_table_type = 'BDB';
 344          } else {
 345              $this->supported['Transactions'] = 0;
 346              $this->default_table_type = '';
 347          }
 348          $DefaultTableType = $this->getOption('DefaultTableType');
 349          if(!MDB::isError($DefaultTableType) && $DefaultTableType) {
 350              switch($this->default_table_type = strtoupper($DefaultTableType)) {
 351                  case 'BERKELEYDB':
 352                      $this->default_table_type = 'BDB';
 353                  case 'BDB':
 354                  case 'INNODB':
 355                  case 'GEMINI':
 356                      break;
 357                  case 'HEAP':
 358                  case 'ISAM':
 359                  case 'MERGE':
 360                  case 'MRG_MYISAM':
 361                  case 'MYISAM':
 362                      if(isset($this->supported['Transactions'])) {
 363                          $this->warnings[] = $DefaultTableType
 364                              .' is not a transaction-safe default table type';
 365                      }
 366                      break;
 367                  default:
 368                      $this->warnings[] = $DefaultTableType
 369                          .' is not a supported default table type';
 370              }
 371          }
 372  
 373          $this->fixed_float = 30;
 374          $function = ($this->options['persistent'] ? 'mysql_pconnect' : 'mysql_connect');
 375          if (!function_exists($function)) {
 376              return($this->raiseError(MDB_ERROR_UNSUPPORTED));
 377          }
 378  
 379          @ini_set('track_errors', TRUE);
 380          $this->connection = @$function(
 381              $this->host.(!strcmp($port,'') ? '' : ':'.$port),
 382              $this->user, $this->password);
 383          @ini_restore('track_errors');
 384          if ($this->connection <= 0) {
 385              return($this->raiseError(MDB_ERROR_CONNECT_FAILED, NULL, NULL,
 386                  $php_errormsg));
 387          }
 388  
 389          if (isset($this->options['fixedfloat'])) {
 390              $this->fixed_float = $this->options['fixedfloat'];
 391          } else {
 392              if (($result = @mysql_query('SELECT VERSION()', $this->connection))) {
 393                  $version = explode('.', @mysql_result($result,0,0));
 394                  $major = intval($version[0]);
 395                  $minor = intval($version[1]);
 396                  $revision = intval($version[2]);
 397                  if ($major > 3 || ($major == 3 && $minor >= 23
 398                      && ($minor > 23 || $revision >= 6)))
 399                  {
 400                      $this->fixed_float = 0;
 401                  }
 402                  @mysql_free_result($result);
 403              }
 404          }
 405          if (isset($this->supported['Transactions']) && !$this->auto_commit) {
 406              if (!@mysql_query('SET AUTOCOMMIT = 0', $this->connection)) {
 407                  @mysql_close($this->connection);
 408                  $this->connection = 0;
 409                  $this->affected_rows = -1;
 410                  return($this->raiseError());
 411              }
 412              $this->in_transaction = TRUE;
 413          }
 414          $this->connected_host = $this->host;
 415          $this->connected_user = $this->user;
 416          $this->connected_password = $this->password;
 417          $this->connected_port = $port;
 418          $this->opened_persistent = $this->getoption('persistent');
 419          return(MDB_OK);
 420      }
 421  
 422      // }}}
 423      // {{{ _close()
 424      /**
 425       * all the RDBMS specific things needed close a DB connection
 426       *
 427       * @return boolean
 428       * @access private
 429       **/
 430      function _close()
 431      {
 432          if ($this->connection != 0) {
 433              if (isset($this->supported['Transactions']) && !$this->auto_commit) {
 434                  $result = $this->autoCommit(TRUE);
 435              }
 436              @mysql_close($this->connection);
 437              $this->connection = 0;
 438              $this->affected_rows = -1;
 439  
 440              if (isset($result) && MDB::isError($result)) {
 441                  return($result);
 442              }
 443              unset($GLOBALS['_MDB_databases'][$this->database]);
 444              return(TRUE);
 445          }
 446          return(FALSE);
 447      }
 448  
 449      // }}}
 450      // {{{ query()
 451  
 452      /**
 453       * Send a query to the database and return any results
 454       *
 455       * @access public
 456       *
 457       * @param string  $query  the SQL query
 458       * @param mixed   $types  array that contains the types of the columns in
 459       *                        the result set
 460       *
 461       * @return mixed a result handle or MDB_OK on success, a MDB error on failure
 462       */
 463      function query($query, $types = NULL)
 464      {
 465          $this->debug("Query: $query");
 466          $ismanip = MDB::isManip($query);
 467          $this->last_query = $query;
 468          $first = $this->first_selected_row;
 469          $limit = $this->selected_row_limit;
 470          $this->first_selected_row = $this->selected_row_limit = 0;
 471  
 472          $result = $this->connect();
 473          if (MDB::isError($result)) {
 474              return($result);
 475          }
 476          if($limit > 0) {
 477              if ($ismanip) {
 478                  $query .= " LIMIT $limit";
 479              } else {
 480                  $query .= " LIMIT $first,$limit";
 481              }
 482          }
 483          if ($this->database_name) {
 484              if(!@mysql_select_db($this->database_name, $this->connection)) {
 485                  return($this->mysqlRaiseError());
 486              }
 487          }
 488          if ($result = @mysql_query($query, $this->connection)) {
 489              if ($ismanip) {
 490                  $this->affected_rows = @mysql_affected_rows($this->connection);
 491                  return(MDB_OK);
 492              } else {
 493                  $result_value = intval($result);
 494                  $this->highest_fetched_row[$result_value] = -1;
 495                  if ($types != NULL) {
 496                      if (!is_array($types)) {
 497                          $types = array($types);
 498                      }
 499                      if (MDB::isError($err = $this->setResultTypes($result, $types))) {
 500                          $this->freeResult($result);
 501                          return($err);
 502                      }
 503                  }
 504                  return($result);
 505              }
 506          }
 507          return($this->mysqlRaiseError());
 508      }
 509  
 510      // }}}
 511      // {{{ subSelect()
 512  
 513      /**
 514       * simple subselect emulation for Mysql
 515       *
 516       * @access public
 517       *
 518       * @param string $query the SQL query for the subselect that may only
 519       *                      return a column
 520       * @param string $quote determines if the data needs to be quoted before
 521       *                      being returned
 522       *
 523       * @return string the query
 524       */
 525      function subSelect($query, $quote = FALSE)
 526      {
 527          if($this->supported['SubSelects'] == 1) {
 528              return($query);
 529          }
 530          $col = $this->queryCol($query);
 531          if (MDB::isError($col)) {
 532              return($col);
 533          }
 534          if(!is_array($col) || count($col) == 0) {
 535              return 'NULL';
 536          }
 537          if($quote) {
 538              for($i = 0, $j = count($col); $i < $j; ++$i) {
 539                  $col[$i] = $this->getTextValue($col[$i]);
 540              }
 541          }
 542          return(implode(', ', $col));
 543      }
 544  
 545      // }}}
 546      // {{{ replace()
 547  
 548      /**
 549       * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
 550       * query, except that if there is already a row in the table with the same
 551       * key field values, the REPLACE query just updates its values instead of
 552       * inserting a new row.
 553       *
 554       * The REPLACE type of query does not make part of the SQL standards. Since
 555       * practically only MySQL implements it natively, this type of query is
 556       * emulated through this method for other DBMS using standard types of
 557       * queries inside a transaction to assure the atomicity of the operation.
 558       *
 559       * @access public
 560       *
 561       * @param string $table name of the table on which the REPLACE query will
 562       *  be executed.
 563       * @param array $fields associative array that describes the fields and the
 564       *  values that will be inserted or updated in the specified table. The
 565       *  indexes of the array are the names of all the fields of the table. The
 566       *  values of the array are also associative arrays that describe the
 567       *  values and other properties of the table fields.
 568       *
 569       *  Here follows a list of field properties that need to be specified:
 570       *
 571       *    Value:
 572       *          Value to be assigned to the specified field. This value may be
 573       *          of specified in database independent type format as this
 574       *          function can perform the necessary datatype conversions.
 575       *
 576       *    Default:
 577       *          this property is required unless the Null property
 578       *          is set to 1.
 579       *
 580       *    Type
 581       *          Name of the type of the field. Currently, all types Metabase
 582       *          are supported except for clob and blob.
 583       *
 584       *    Default: no type conversion
 585       *
 586       *    Null
 587       *          Boolean property that indicates that the value for this field
 588       *          should be set to NULL.
 589       *
 590       *          The default value for fields missing in INSERT queries may be
 591       *          specified the definition of a table. Often, the default value
 592       *          is already NULL, but since the REPLACE may be emulated using
 593       *          an UPDATE query, make sure that all fields of the table are
 594       *          listed in this function argument array.
 595       *
 596       *    Default: 0
 597       *
 598       *    Key
 599       *          Boolean property that indicates that this field should be
 600       *          handled as a primary key or at least as part of the compound
 601       *          unique index of the table that will determine the row that will
 602       *          updated if it exists or inserted a new row otherwise.
 603       *
 604       *          This function will fail if no key field is specified or if the
 605       *          value of a key field is set to NULL because fields that are
 606       *          part of unique index they may not be NULL.
 607       *
 608       *    Default: 0
 609       *
 610       * @return mixed MDB_OK on success, a MDB error on failure
 611       */
 612      function replace($table, $fields)
 613      {
 614          $count = count($fields);
 615          for($keys = 0, $query = $values = '',reset($fields), $field = 0;
 616              $field<$count;
 617              next($fields), $field++)
 618          {
 619              $name = key($fields);
 620              if ($field > 0) {
 621                  $query .= ',';
 622                  $values .= ',';
 623              }
 624              $query .= $name;
 625              if (isset($fields[$name]['Null']) && $fields[$name]['Null']) {
 626                  $value = 'NULL';
 627              } else {
 628                  if(isset($fields[$name]['Type'])) {
 629                      switch ($fields[$name]['Type']) {
 630                          case 'text':
 631                              $value = $this->getTextValue($fields[$name]['Value']);
 632                              break;
 633                          case 'boolean':
 634                              $value = $this->getBooleanValue($fields[$name]['Value']);
 635                              break;
 636                          case 'integer':
 637                              $value = $this->getIntegerValue($fields[$name]['Value']);
 638                              break;
 639                          case 'decimal':
 640                              $value = $this->getDecimalValue($fields[$name]['Value']);
 641                              break;
 642                          case 'float':
 643                              $value = $this->getFloatValue($fields[$name]['Value']);
 644                              break;
 645                          case 'date':
 646                              $value = $this->getDateValue($fields[$name]['Value']);
 647                              break;
 648                          case 'time':
 649                              $value = $this->getTimeValue($fields[$name]['Value']);
 650                              break;
 651                          case 'timestamp':
 652                              $value = $this->getTimestampValue($fields[$name]['Value']);
 653                              break;
 654                          default:
 655                              return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
 656                                  'no supported type for field "' . $name . '" specified'));
 657                      }
 658                  } else {
 659                      $value = $fields[$name]['Value'];
 660                  }
 661              }
 662              $values .= $value;
 663              if (isset($fields[$name]['Key']) && $fields[$name]['Key']) {
 664                  if ($value === 'NULL') {
 665                      return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
 666                          $name.': key values may not be NULL'));
 667                  }
 668                  $keys++;
 669              }
 670          }
 671          if ($keys == 0) {
 672              return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
 673                  'not specified which fields are keys'));
 674          }
 675          return($this->query("REPLACE INTO $table ($query) VALUES ($values)"));
 676      }
 677  
 678      // }}}
 679      // {{{ getColumnNames()
 680  
 681      /**
 682       * Retrieve the names of columns returned by the DBMS in a query result.
 683       *
 684       * @param resource   $result    result identifier
 685       * @return mixed                an associative array variable
 686       *                              that will hold the names of columns. The
 687       *                              indexes of the array are the column names
 688       *                              mapped to lower case and the values are the
 689       *                              respective numbers of the columns starting
 690       *                              from 0. Some DBMS may not return any
 691       *                              columns when the result set does not
 692       *                              contain any rows.
 693       *
 694       *                              a MDB error on failure
 695       * @access public
 696       */
 697      function getColumnNames($result)
 698      {
 699          $result_value = intval($result);
 700          if (!isset($this->highest_fetched_row[$result_value])) {
 701              return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
 702                  'Get column names: it was specified an inexisting result set'));
 703          }
 704          if (!isset($this->columns[$result_value])) {
 705              $this->columns[$result_value] = array();
 706              $columns = @mysql_num_fields($result);
 707              for($column = 0; $column < $columns; $column++) {
 708                  $field_name = @mysql_field_name($result, $column);
 709                  if ($this->options['optimize'] == 'portability') {
 710                      $field_name = strtolower($field_name);
 711                  }
 712                  $this->columns[$result_value][$field_name] = $column;
 713              }
 714          }
 715          return($this->columns[$result_value]);
 716      }
 717  
 718      // }}}
 719      // {{{ numCols()
 720  
 721      /**
 722       * Count the number of columns returned by the DBMS in a query result.
 723       *
 724       * @param resource    $result        result identifier
 725       * @access public
 726       * @return mixed integer value with the number of columns, a MDB error
 727       *                       on failure
 728       */
 729      function numCols($result)
 730      {
 731          $result_value = intval($result);
 732          if (!isset($this->highest_fetched_row[$result_value])) {
 733              return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
 734                  'numCols: it was specified an inexisting result set'));
 735          }
 736          return(@mysql_num_fields($result));
 737      }
 738  
 739      // }}}
 740      // {{{ endOfResult()
 741  
 742      /**
 743      * check if the end of the result set has been reached
 744      *
 745      * @param resource    $result result identifier
 746      * @return mixed TRUE or FALSE on sucess, a MDB error on failure
 747      * @access public
 748      */
 749      function endOfResult($result)
 750      {
 751          $result_value = intval($result);
 752          if (!isset($this->highest_fetched_row[$result_value])) {
 753              return($this->raiseError(MDB_ERROR, NULL, NULL,
 754                  'End of result: attempted to check the end of an unknown result'));
 755          }
 756          return($this->highest_fetched_row[$result_value] >= $this->numRows($result)-1);
 757      }
 758  
 759      // }}}
 760      // {{{ fetch()
 761  
 762      /**
 763      * fetch value from a result set
 764      *
 765      * @param resource    $result result identifier
 766      * @param int    $row    number of the row where the data can be found
 767      * @param int    $field    field number where the data can be found
 768      * @return mixed string on success, a MDB error on failure
 769      * @access public
 770      */
 771      function fetch($result, $row, $field)
 772      {
 773          $result_value = intval($result);
 774          $this->highest_fetched_row[$result_value] =
 775              max($this->highest_fetched_row[$result_value], $row);
 776          $res = @mysql_result($result, $row, $field);
 777          if ($res === FALSE && $res != NULL) {
 778              return($this->mysqlRaiseError());
 779          }
 780          return($res);
 781      }
 782  
 783      // }}}
 784      // {{{ fetchClob()
 785  
 786      /**
 787      * fetch a clob value from a result set
 788      *
 789      * @param resource    $result result identifier
 790      * @param int    $row    number of the row where the data can be found
 791      * @param int    $field    field number where the data can be found
 792      * @return mixed content of the specified data cell, a MDB error on failure,
 793      *               a MDB error on failure
 794      * @access public
 795      */
 796      function fetchClob($result, $row, $field)
 797      {
 798          return($this->fetchLob($result, $row, $field));
 799      }
 800  
 801      // }}}
 802      // {{{ fetchBlob()
 803  
 804      /**
 805      * fetch a blob value from a result set
 806      *
 807      * @param resource    $result result identifier
 808      * @param int    $row    number of the row where the data can be found
 809      * @param int    $field    field number where the data can be found
 810      * @return mixed content of the specified data cell, a MDB error on failure
 811      * @access public
 812      */
 813      function fetchBlob($result, $row, $field)
 814      {
 815          return($this->fetchLob($result, $row, $field));
 816      }
 817  
 818      // }}}
 819      // {{{ convertResult()
 820  
 821      /**
 822      * convert a value to a RDBMS indepdenant MDB type
 823      *
 824      * @param mixed  $value   value to be converted
 825      * @param int    $type    constant that specifies which type to convert to
 826      * @return mixed converted value
 827      * @access public
 828      */
 829      function convertResult($value, $type)
 830      {
 831          switch($type) {
 832              case MDB_TYPE_DECIMAL:
 833                  return(sprintf('%.'.$this->decimal_places.'f', doubleval($value)/$this->decimal_factor));
 834              default:
 835                  return($this->_baseConvertResult($value, $type));
 836          }
 837      }
 838  
 839      // }}}
 840      // {{{ numRows()
 841  
 842      /**
 843      * returns the number of rows in a result object
 844      *
 845       * @param ressource $result a valid result ressouce pointer
 846      * @return mixed MDB_Error or the number of rows
 847      * @access public
 848      */
 849      function numRows($result)
 850      {
 851          return(@mysql_num_rows($result));
 852      }
 853  
 854      // }}}
 855      // {{{ freeResult()
 856  
 857      /**
 858       * Free the internal resources associated with $result.
 859       *
 860       * @param $result result identifier
 861       * @return boolean TRUE on success, FALSE if $result is invalid
 862       * @access public
 863       */
 864      function freeResult($result)
 865      {
 866          $result_value = intval($result);
 867          if(isset($this->highest_fetched_row[$result_value])) {
 868              unset($this->highest_fetched_row[$result_value]);
 869          }
 870          if(isset($this->columns[$result_value])) {
 871              unset($this->columns[$result_value]);
 872          }
 873          if(isset($this->result_types[$result_value])) {
 874              unset($this->result_types[$result_value]);
 875          }
 876          return(@mysql_free_result($result));
 877      }
 878  
 879      // }}}
 880      // {{{ getIntegerDeclaration()
 881  
 882      /**
 883       * Obtain DBMS specific SQL code portion needed to declare an integer type
 884       * field to be used in statements like CREATE TABLE.
 885       *
 886       * @param string  $name   name the field to be declared.
 887       * @param string  $field  associative array with the name of the properties
 888       *                        of the field being declared as array indexes.
 889       *                        Currently, the types of supported field
 890       *                        properties are as follows:
 891       *
 892       *                       unsigned
 893       *                        Boolean flag that indicates whether the field
 894       *                        should be declared as unsigned integer if
 895       *                        possible.
 896       *
 897       *                       default
 898       *                        Integer value to be used as default for this
 899       *                        field.
 900       *
 901       *                       notnull
 902       *                        Boolean flag that indicates whether this field is
 903       *                        constrained to not be set to NULL.
 904       * @return string  DBMS specific SQL code portion that should be used to
 905       *                 declare the specified field.
 906       * @access public
 907       */
 908      function getIntegerDeclaration($name, $field)
 909      {
 910          return("$name INT".
 911                  (isset($field['unsigned']) ? ' UNSIGNED' : '').
 912                  (isset($field['default']) ? ' DEFAULT '.$field['default'] : '').
 913                  (isset($field['notnull']) ? ' NOT NULL' : '')
 914                 );
 915      }
 916  
 917      // }}}
 918      // {{{ getClobDeclaration()
 919  
 920      /**
 921       * Obtain DBMS specific SQL code portion needed to declare an character
 922       * large object type field to be used in statements like CREATE TABLE.
 923       *
 924       * @param string  $name   name the field to be declared.
 925       * @param string  $field  associative array with the name of the
 926       *                        properties of the field being declared as array
 927       *                        indexes. Currently, the types of supported field
 928       *                        properties are as follows:
 929       *
 930       *                       length
 931       *                        Integer value that determines the maximum length
 932       *                        of the large object field. If this argument is
 933       *                        missing the field should be declared to have the
 934       *                        longest length allowed by the DBMS.
 935       *
 936       *                       notnull
 937       *                        Boolean flag that indicates whether this field
 938       *                        is constrained to not be set to NULL.
 939       * @return string  DBMS specific SQL code portion that should be used to
 940       *                 declare the specified field.
 941       * @access public
 942       */
 943      function getClobDeclaration($name, $field)
 944      {
 945          if (isset($field['length'])) {
 946              $length = $field['length'];
 947              if ($length <= 255) {
 948                  $type = 'TINYTEXT';
 949              } else {
 950                  if ($length <= 65535) {
 951                      $type = 'TEXT';
 952                  } else {
 953                      if ($length <= 16777215) {
 954                          $type = 'MEDIUMTEXT';
 955                      } else {
 956                          $type = 'LONGTEXT';
 957                      }
 958                  }
 959              }
 960          } else {
 961              $type = 'LONGTEXT';
 962          }
 963          return("$name $type".
 964                   (isset($field['notnull']) ? ' NOT NULL' : ''));
 965      }
 966  
 967      // }}}
 968      // {{{ getBlobDeclaration()
 969  
 970      /**
 971       * Obtain DBMS specific SQL code portion needed to declare an binary large
 972       * object type field to be used in statements like CREATE TABLE.
 973       *
 974       * @param string  $name   name the field to be declared.
 975       * @param string  $field  associative array with the name of the properties
 976       *                        of the field being declared as array indexes.
 977       *                        Currently, the types of supported field
 978       *                        properties are as follows:
 979       *
 980       *                       length
 981       *                        Integer value that determines the maximum length
 982       *                        of the large object field. If this argument is
 983       *                        missing the field should be declared to have the
 984       *                        longest length allowed by the DBMS.
 985       *
 986       *                       notnull
 987       *                        Boolean flag that indicates whether this field is
 988       *                        constrained to not be set to NULL.
 989       * @return string  DBMS specific SQL code portion that should be used to
 990       *                 declare the specified field.
 991       * @access public
 992       */
 993      function getBlobDeclaration($name, $field)
 994      {
 995          if (isset($field['length'])) {
 996              $length = $field['length'];
 997              if ($length <= 255) {
 998                  $type = 'TINYBLOB';
 999              } else {
1000                  if ($length <= 65535) {
1001                      $type = 'BLOB';
1002                  } else {
1003                      if ($length <= 16777215) {
1004                          $type = 'MEDIUMBLOB';
1005                      } else {
1006                          $type = 'LONGBLOB';
1007                      }
1008                  }
1009              }
1010          }
1011          else {
1012              $type = 'LONGBLOB';
1013          }
1014          return("$name $type".
1015                  (isset($field['notnull']) ? ' NOT NULL' : ''));
1016      }
1017  
1018      // }}}
1019      // {{{ getDateDeclaration()
1020  
1021      /**
1022       * Obtain DBMS specific SQL code portion needed to declare an date type
1023       * field to be used in statements like CREATE TABLE.
1024       *
1025       * @param string  $name   name the field to be declared.
1026       * @param string  $field  associative array with the name of the properties
1027       *                        of the field being declared as array indexes.
1028       *                        Currently, the types of supported field properties
1029       *                        are as follows:
1030       *
1031       *                       default
1032       *                        Date value to be used as default for this field.
1033       *
1034       *                       notnull
1035       *                        Boolean flag that indicates whether this field is
1036       *                        constrained to not be set to NULL.
1037       * @return string  DBMS specific SQL code portion that should be used to
1038       *                 declare the specified field.
1039       * @access public
1040       */
1041      function getDateDeclaration($name, $field)
1042      {
1043          return("$name DATE".
1044                  (isset($field['default']) ? " DEFAULT '".$field['default']."'" : '').
1045                  (isset($field['notnull']) ? ' NOT NULL' : '')
1046                 );
1047      }
1048  
1049      // }}}
1050      // {{{ getTimestampDeclaration()
1051  
1052      /**
1053       * Obtain DBMS specific SQL code portion needed to declare an timestamp
1054       * type field to be used in statements like CREATE TABLE.
1055       *
1056       * @param string  $name   name the field to be declared.
1057       * @param string  $field  associative array with the name of the properties
1058       *                        of the field being declared as array indexes.
1059       *                        Currently, the types of supported field
1060       *                        properties are as follows:
1061       *
1062       *                       default
1063       *                        Time stamp value to be used as default for this
1064       *                        field.
1065       *
1066       *                       notnull
1067       *                        Boolean flag that indicates whether this field is
1068       *                        constrained to not be set to NULL.
1069       * @return string  DBMS specific SQL code portion that should be used to
1070       *                 declare the specified field.
1071       * @access public
1072       */
1073      function getTimestampDeclaration($name, $field)
1074      {
1075          return("$name DATETIME".
1076                  (isset($field['default']) ? " DEFAULT '".$field['default']."'" : '').
1077                  (isset($field['notnull']) ? ' NOT NULL' : '')
1078                 );
1079      }
1080  
1081      // }}}
1082      // {{{ getTimeDeclaration()
1083  
1084      /**
1085       * Obtain DBMS specific SQL code portion needed to declare an time type
1086       * field to be used in statements like CREATE TABLE.
1087       *
1088       * @param string  $name   name the field to be declared.
1089       * @param string  $field  associative array with the name of the properties
1090       *                        of the field being declared as array indexes.
1091       *                        Currently, the types of supported field
1092       *                        properties are as follows:
1093       *
1094       *                       default
1095       *                        Time value to be used as default for this field.
1096       *
1097       *                       notnull
1098       *                        Boolean flag that indicates whether this field is
1099       *                        constrained to not be set to NULL.
1100       * @return string  DBMS specific SQL code portion that should be used to
1101       *                 declare the specified field.
1102       * @access public
1103       */
1104      function getTimeDeclaration($name, $field)
1105      {
1106          return("$name TIME".
1107                  (isset($field['default']) ? " DEFAULT '".$field['default']."'" : '').
1108                  (isset($field['notnull']) ? ' NOT NULL' : '')
1109                 );
1110      }
1111  
1112      // }}}
1113      // {{{ getFloatDeclaration()
1114  
1115      /**
1116       * Obtain DBMS specific SQL code portion needed to declare an float type
1117       * field to be used in statements like CREATE TABLE.
1118       *
1119       * @param string  $name   name the field to be declared.
1120       * @param string  $field  associative array with the name of the properties
1121       *                        of the field being declared as array indexes.
1122       *                        Currently, the types of supported field
1123       *                        properties are as follows:
1124       *
1125       *                       default
1126       *                        Integer value to be used as default for this
1127       *                        field.
1128       *
1129       *                       notnull
1130       *                        Boolean flag that indicates whether this field is
1131       *                        constrained to not be set to NULL.
1132       * @return string  DBMS specific SQL code portion that should be used to
1133       *                 declare the specified field.
1134       * @access public
1135       */
1136      function getFloatDeclaration($name, $field)
1137      {
1138          if (isset($this->options['fixedfloat'])) {
1139              $this->fixed_float = $this->options['fixedfloat'];
1140          } else {
1141              if ($this->connection == 0) {
1142                  // XXX needs more checking
1143                  $this->connect();
1144              }
1145          }
1146          return("$name DOUBLE".
1147                  ($this->fixed_float ?
1148                   '('.($this->fixed_float + 2).','.$this->fixed_float.')' : '').
1149                  (isset($field['default']) ?
1150                   ' DEFAULT '.$this->getFloatValue($field['default']) : '').
1151                  (isset($field['notnull']) ? ' NOT NULL' : '')
1152                 );
1153      }
1154  
1155      // }}}
1156      // {{{ getDecimalDeclaration()
1157  
1158      /**
1159       * Obtain DBMS specific SQL code portion needed to declare an decimal type
1160       * field to be used in statements like CREATE TABLE.
1161       *
1162       * @param string  $name   name the field to be declared.
1163       * @param string  $field  associative array with the name of the properties
1164       *                        of the field being declared as array indexes.
1165       *                        Currently, the types of supported field
1166       *                        properties are as follows:
1167       *
1168       *                       default
1169       *                        Integer value to be used as default for this
1170       *                        field.
1171       *
1172       *                       notnull
1173       *                        Boolean flag that indicates whether this field is
1174       *                        constrained to not be set to NULL.
1175       * @return string  DBMS specific SQL code portion that should be used to
1176       *                 declare the specified field.
1177       * @access public
1178       */
1179      function getDecimalDeclaration($name, $field)
1180      {
1181          return("$name BIGINT".
1182                  (isset($field['default']) ?
1183                   ' DEFAULT '.$this->getDecimalValue($field['default']) : '').
1184                   (isset($field['notnull']) ? ' NOT NULL' : '')
1185                 );
1186      }
1187  
1188      // }}}
1189      // {{{ getClobValue()
1190  
1191      /**
1192       * Convert a text value into a DBMS specific format that is suitable to
1193       * compose query statements.
1194       *
1195       * @param resource  $prepared_query query handle from prepare()
1196       * @param           $parameter
1197       * @param           $clob
1198       * @return string  text string that represents the given argument value in
1199       *                 a DBMS specific format.
1200       * @access public
1201       */
1202      function getClobValue($prepared_query, $parameter, $clob)
1203      {
1204          $value = "'";
1205          while(!$this->endOfLob($clob)) {
1206              if (MDB::isError($result = $this->readLob($clob, $data, $this->options['lob_buffer_length']))) {
1207                  return($result);
1208              }
1209              $value .= $this->_quote($data);
1210          }
1211          $value .= "'";
1212          return($value);
1213      }
1214  
1215      // }}}
1216      // {{{ freeClobValue()
1217  
1218      /**
1219       * free a character large object
1220       *
1221       * @param resource  $prepared_query query handle from prepare()
1222       * @param string    $clob
1223       * @return MDB_OK
1224       * @access public
1225       */
1226      function freeClobValue($prepared_query, $clob)
1227      {
1228          unset($this->lobs[$clob]);
1229          return(MDB_OK);
1230      }
1231  
1232      // }}}
1233      // {{{ getBlobValue()
1234  
1235      /**
1236       * Convert a text value into a DBMS specific format that is suitable to
1237       * compose query statements.
1238       *
1239       * @param resource  $prepared_query query handle from prepare()
1240       * @param           $parameter
1241       * @param           $blob
1242       * @return string  text string that represents the given argument value in
1243       *                 a DBMS specific format.
1244       * @access public
1245       */
1246      function getBlobValue($prepared_query, $parameter, $blob)
1247      {
1248          $value = "'";
1249          while(!$this->endOfLob($blob)) {
1250              if (MDB::isError($result = $this->readLob($blob, $data, $this->options['lob_buffer_length']))) {
1251                  return($result);
1252              }
1253              $value .= addslashes($data);
1254          }
1255          $value .= "'";
1256          return($value);
1257      }
1258  
1259      // }}}
1260      // {{{ freeBlobValue()
1261  
1262      /**
1263       * free a binary large object
1264       *
1265       * @param resource  $prepared_query query handle from prepare()
1266       * @param string    $blob
1267       * @return MDB_OK
1268       * @access public
1269       */
1270      function freeBlobValue($prepared_query, $blob)
1271      {
1272          unset($this->lobs[$blob]);
1273          return(MDB_OK);
1274      }
1275  
1276      // }}}
1277      // {{{ getFloatValue()
1278  
1279      /**
1280       * Convert a text value into a DBMS specific format that is suitable to
1281       * compose query statements.
1282       *
1283       * @param string  $value text string value that is intended to be converted.
1284       * @return string  text string that represents the given argument value in
1285       *                 a DBMS specific format.
1286       * @access public
1287       */
1288      function getFloatValue($value)
1289      {
1290          return(($value === NULL) ? 'NULL' : (float)$value);
1291      }
1292  
1293      // }}}
1294      // {{{ getDecimalValue()
1295  
1296      /**
1297       * Convert a text value into a DBMS specific format that is suitable to
1298       * compose query statements.
1299       *
1300       * @param string  $value text string value that is intended to be converted.
1301       * @return string  text string that represents the given argument value in
1302       *                 a DBMS specific format.
1303       * @access public
1304       */
1305      function getDecimalValue($value)
1306      {
1307          return(($value === NULL) ? 'NULL' : strval(round(doubleval($value)*$this->decimal_factor)));
1308      }
1309  
1310      // }}}
1311      // {{{ nextId()
1312  
1313      /**
1314       * returns the next free id of a sequence
1315       *
1316       * @param string  $seq_name name of the sequence
1317       * @param boolean $ondemand when true the seqence is
1318       *                          automatic created, if it
1319       *                          not exists
1320       *
1321       * @return mixed MDB_Error or id
1322       * @access public
1323       */
1324      function nextId($seq_name, $ondemand = TRUE)
1325      {
1326          $sequence_name = $this->getSequenceName($seq_name);
1327          $this->expectError(MDB_ERROR_NOSUCHTABLE);
1328          $result = $this->query("INSERT INTO $sequence_name ("
1329              .$this->options['sequence_col_name'].") VALUES (NULL)");
1330          $this->popExpect();
1331          if ($ondemand && MDB::isError($result) &&
1332              $result->getCode() == MDB_ERROR_NOSUCHTABLE)
1333          {
1334              // Since we are create the sequence on demand
1335              // we know the first id = 1 so initialize the
1336              // sequence at 2
1337              $result = $this->createSequence($seq_name, 2);
1338              if (MDB::isError($result)) {
1339                  return($this->raiseError(MDB_ERROR, NULL, NULL,
1340                      'Next ID: on demand sequence could not be created'));
1341              } else {
1342                  // First ID of a newly created sequence is 1
1343                  return(1);
1344              }
1345          }
1346          $value = intval(@mysql_insert_id($this->connection));
1347          $res = $this->query("DELETE FROM $sequence_name WHERE "
1348              .$this->options['sequence_col_name']." < $value");
1349          if (MDB::isError($res)) {
1350              $this->warnings[] = 'Next ID: could not delete previous sequence table values';
1351          }
1352          return($value);
1353      }
1354  
1355  
1356      // }}}
1357      // {{{ currId()
1358  
1359      /**
1360       * returns the current id of a sequence
1361       *
1362       * @param string  $seq_name name of the sequence
1363       * @return mixed MDB_Error or id
1364       * @access public
1365       */
1366      function currId($seq_name)
1367      {
1368          $sequence_name = $this->getSequenceName($seq_name);
1369          $result = $this->query("SELECT MAX(".$this->options['sequence_col_name'].") FROM $sequence_name", 'integer');
1370          if (MDB::isError($result)) {
1371              return($result);
1372          }
1373  
1374          return($this->fetchOne($result));
1375      }
1376  
1377      // }}}
1378      // {{{ fetchInto()
1379  
1380      /**
1381       * Fetch a row and insert the data into an existing array.
1382       *
1383       * @param resource  $result     result identifier
1384       * @param int       $fetchmode  how the array data should be indexed
1385       * @param int       $rownum     the row number to fetch
1386       * @return int data array on success, a MDB error on failure
1387       * @access public
1388       */
1389      function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL)
1390      {
1391          $result_value = intval($result);
1392          if ($rownum == NULL) {
1393              ++$this->highest_fetched_row[$result_value];
1394          } else {
1395              if (!@mysql_data_seek($result, $rownum)) {
1396                  return(NULL);
1397              }
1398              $this->highest_fetched_row[$result_value] =
1399                  max($this->highest_fetched_row[$result_value], $rownum);
1400          }
1401          if ($fetchmode == MDB_FETCHMODE_DEFAULT) {
1402              $fetchmode = $this->fetchmode;
1403          }
1404          if ($fetchmode & MDB_FETCHMODE_ASSOC) {
1405              $row = @mysql_fetch_assoc($result);
1406              if (is_array($row) && $this->options['optimize'] == 'portability') {
1407                  $row = array_change_key_case($row, CASE_LOWER);
1408              }
1409          } else {
1410              $row = @mysql_fetch_row($result);
1411          }
1412          if (!$row) {
1413              if($this->options['autofree']) {
1414                  $this->freeResult($result);
1415              }
1416              return(NULL);
1417          }
1418          if (isset($this->result_types[$result_value])) {
1419              $row = $this->convertResultRow($result, $row);
1420          }
1421          return($row);
1422      }
1423  
1424      // }}}
1425      // {{{ nextResult()
1426  
1427      /**
1428       * Move the internal mysql result pointer to the next available result
1429       * Currently not supported
1430       *
1431       * @param a valid result resource
1432       * @return true if a result is available otherwise return false
1433       * @access public
1434       */
1435      function nextResult($result)
1436      {
1437          return(FALSE);
1438      }
1439  
1440      // }}}
1441      // {{{ tableInfo()
1442  
1443      /**
1444      * returns meta data about the result set
1445      *
1446      * @param resource    $result    result identifier
1447      * @param mixed $mode depends on implementation
1448      * @return array an nested array, or a MDB error
1449      * @access public
1450      */
1451      function tableInfo($result, $mode = NULL) {
1452          $count = 0;
1453          $id     = 0;
1454          $res  = array();
1455  
1456          /*
1457           * depending on $mode, metadata returns the following values:
1458           *
1459           * - mode is false (default):
1460           * $result[]:
1461           *   [0]['table']  table name
1462           *   [0]['name']   field name
1463           *   [0]['type']   field type
1464           *   [0]['len']    field length
1465           *   [0]['flags']  field flags
1466           *
1467           * - mode is MDB_TABLEINFO_ORDER
1468           * $result[]:
1469           *   ['num_fields'] number of metadata records
1470           *   [0]['table']  table name
1471           *   [0]['name']   field name
1472           *   [0]['type']   field type
1473           *   [0]['len']    field length
1474           *   [0]['flags']  field flags
1475           *   ['order'][field name]  index of field named "field name"
1476           *   The last one is used, if you have a field name, but no index.
1477           *   Test:  if (isset($result['meta']['myfield'])) { ...
1478           *
1479           * - mode is MDB_TABLEINFO_ORDERTABLE
1480           *    the same as above. but additionally
1481           *   ['ordertable'][table name][field name] index of field
1482           *      named 'field name'
1483           *
1484           *      this is, because if you have fields from different
1485           *      tables with the same field name * they override each
1486           *      other with MDB_TABLEINFO_ORDER
1487           *
1488           *      you can combine MDB_TABLEINFO_ORDER and
1489           *      MDB_TABLEINFO_ORDERTABLE with MDB_TABLEINFO_ORDER |
1490           *      MDB_TABLEINFO_ORDERTABLE * or with MDB_TABLEINFO_FULL
1491           */
1492  
1493          // if $result is a string, then we want information about a
1494          // table without a resultset
1495          if (is_string($result)) {
1496              if (MDB::isError($connect = $this->connect())) {
1497                  return $connect;
1498              }
1499              $id = @mysql_list_fields($this->database_name,
1500                  $result, $this->connection);
1501              if (empty($id)) {
1502                  return($this->mysqlRaiseError());
1503              }
1504          } else { // else we want information about a resultset
1505              $id = $result;
1506              if (empty($id)) {
1507                  return($this->mysqlRaiseError());
1508              }
1509          }
1510  
1511          $count = @mysql_num_fields($id);
1512  
1513          // made this IF due to performance (one if is faster than $count if's)
1514          if (empty($mode)) {
1515              for ($i = 0, $j = 0; $i<$count; $i++) {
1516                  $name = @mysql_field_name($id, $i);
1517                  if ($name != 'dummy_primary_key') {
1518                      $res[$j]['table'] = @mysql_field_table($id, $i);
1519                      $res[$j]['name'] = $name;
1520                      $res[$j]['type'] = @mysql_field_type($id, $i);
1521                      $res[$j]['len']  = @mysql_field_len($id, $i);
1522                      $res[$j]['flags'] = @mysql_field_flags($id, $i);
1523                      $j++;
1524                  }
1525              }
1526          } else { // full
1527              $res['num_fields'] = $count;
1528  
1529              for ($i = 0; $i<$count; $i++) {
1530                  $name = @mysql_field_name($id, $i);
1531                  if ($name != 'dummy_primary_key') {
1532                      $res[$j]['table'] = @mysql_field_table($id, $i);
1533                      $res[$j]['name'] = $name;
1534                      $res[$j]['type'] = @mysql_field_type($id, $i);
1535                      $res[$j]['len']  = @mysql_field_len($id, $i);
1536                      $res[$j]['flags'] = @mysql_field_flags($id, $i);
1537                      if ($mode & MDB_TABLEINFO_ORDER) {
1538                          // note sure if this should be $i or $j
1539                          $res['order'][$res[$j]['name']] = $i;
1540                      }
1541                      if ($mode & MDB_TABLEINFO_ORDERTABLE) {
1542                          $res['ordertable'][$res[$j]['table']][$res[$j]['name']] = $j;
1543                      }
1544                      $j++;
1545                  }
1546              }
1547          }
1548  
1549          // free the result only if we were called on a table
1550          if (is_string($result)) {
1551              @mysql_free_result($id);
1552          }
1553          return($res);
1554      }
1555  }
1556  
1557  ?>


Généré le : Sun Feb 25 14:08:00 2007 par Balluche grâce à PHPXref 0.7