[ Index ]
 

Code source de PHP PEAR 1.4.5

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

title

Body

[fermer]

/DB/ -> mysql.php (source)

   1  <?php
   2  
   3  /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
   4  
   5  /**
   6   * The PEAR DB driver for PHP's mysql extension
   7   * for interacting with MySQL databases
   8   *
   9   * PHP versions 4 and 5
  10   *
  11   * LICENSE: This source file is subject to version 3.0 of the PHP license
  12   * that is available through the world-wide-web at the following URI:
  13   * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  14   * the PHP License and are unable to obtain it through the web, please
  15   * send a note to license@php.net so we can mail you a copy immediately.
  16   *
  17   * @category   Database
  18   * @package    DB
  19   * @author     Stig Bakken <ssb@php.net>
  20   * @author     Daniel Convissor <danielc@php.net>
  21   * @copyright  1997-2005 The PHP Group
  22   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  23   * @version    CVS: $Id: mysql.php,v 1.124 2007/01/12 03:11:17 aharvey Exp $
  24   * @link       http://pear.php.net/package/DB
  25   */
  26  
  27  /**
  28   * Obtain the DB_common class so it can be extended from
  29   */
  30  require_once  'DB/common.php';
  31  
  32  /**
  33   * The methods PEAR DB uses to interact with PHP's mysql extension
  34   * for interacting with MySQL databases
  35   *
  36   * These methods overload the ones declared in DB_common.
  37   *
  38   * @category   Database
  39   * @package    DB
  40   * @author     Stig Bakken <ssb@php.net>
  41   * @author     Daniel Convissor <danielc@php.net>
  42   * @copyright  1997-2005 The PHP Group
  43   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  44   * @version    Release: 1.7.9
  45   * @link       http://pear.php.net/package/DB
  46   */
  47  class DB_mysql extends DB_common
  48  {
  49      // {{{ properties
  50  
  51      /**
  52       * The DB driver type (mysql, oci8, odbc, etc.)
  53       * @var string
  54       */
  55      var $phptype = 'mysql';
  56  
  57      /**
  58       * The database syntax variant to be used (db2, access, etc.), if any
  59       * @var string
  60       */
  61      var $dbsyntax = 'mysql';
  62  
  63      /**
  64       * The capabilities of this DB implementation
  65       *
  66       * The 'new_link' element contains the PHP version that first provided
  67       * new_link support for this DBMS.  Contains false if it's unsupported.
  68       *
  69       * Meaning of the 'limit' element:
  70       *   + 'emulate' = emulate with fetch row by number
  71       *   + 'alter'   = alter the query
  72       *   + false     = skip rows
  73       *
  74       * @var array
  75       */
  76      var $features = array(
  77          'limit'         => 'alter',
  78          'new_link'      => '4.2.0',
  79          'numrows'       => true,
  80          'pconnect'      => true,
  81          'prepare'       => false,
  82          'ssl'           => false,
  83          'transactions'  => true,
  84      );
  85  
  86      /**
  87       * A mapping of native error codes to DB error codes
  88       * @var array
  89       */
  90      var $errorcode_map = array(
  91          1004 => DB_ERROR_CANNOT_CREATE,
  92          1005 => DB_ERROR_CANNOT_CREATE,
  93          1006 => DB_ERROR_CANNOT_CREATE,
  94          1007 => DB_ERROR_ALREADY_EXISTS,
  95          1008 => DB_ERROR_CANNOT_DROP,
  96          1022 => DB_ERROR_ALREADY_EXISTS,
  97          1044 => DB_ERROR_ACCESS_VIOLATION,
  98          1046 => DB_ERROR_NODBSELECTED,
  99          1048 => DB_ERROR_CONSTRAINT,
 100          1049 => DB_ERROR_NOSUCHDB,
 101          1050 => DB_ERROR_ALREADY_EXISTS,
 102          1051 => DB_ERROR_NOSUCHTABLE,
 103          1054 => DB_ERROR_NOSUCHFIELD,
 104          1061 => DB_ERROR_ALREADY_EXISTS,
 105          1062 => DB_ERROR_ALREADY_EXISTS,
 106          1064 => DB_ERROR_SYNTAX,
 107          1091 => DB_ERROR_NOT_FOUND,
 108          1100 => DB_ERROR_NOT_LOCKED,
 109          1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
 110          1142 => DB_ERROR_ACCESS_VIOLATION,
 111          1146 => DB_ERROR_NOSUCHTABLE,
 112          1216 => DB_ERROR_CONSTRAINT,
 113          1217 => DB_ERROR_CONSTRAINT,
 114          1356 => DB_ERROR_DIVZERO,
 115          1451 => DB_ERROR_CONSTRAINT,
 116          1452 => DB_ERROR_CONSTRAINT,
 117      );
 118  
 119      /**
 120       * The raw database connection created by PHP
 121       * @var resource
 122       */
 123      var $connection;
 124  
 125      /**
 126       * The DSN information for connecting to a database
 127       * @var array
 128       */
 129      var $dsn = array();
 130  
 131  
 132      /**
 133       * Should data manipulation queries be committed automatically?
 134       * @var bool
 135       * @access private
 136       */
 137      var $autocommit = true;
 138  
 139      /**
 140       * The quantity of transactions begun
 141       *
 142       * {@internal  While this is private, it can't actually be designated
 143       * private in PHP 5 because it is directly accessed in the test suite.}}
 144       *
 145       * @var integer
 146       * @access private
 147       */
 148      var $transaction_opcount = 0;
 149  
 150      /**
 151       * The database specified in the DSN
 152       *
 153       * It's a fix to allow calls to different databases in the same script.
 154       *
 155       * @var string
 156       * @access private
 157       */
 158      var $_db = '';
 159  
 160  
 161      // }}}
 162      // {{{ constructor
 163  
 164      /**
 165       * This constructor calls <kbd>$this->DB_common()</kbd>
 166       *
 167       * @return void
 168       */
 169      function DB_mysql()
 170      {
 171          $this->DB_common();
 172      }
 173  
 174      // }}}
 175      // {{{ connect()
 176  
 177      /**
 178       * Connect to the database server, log in and open the database
 179       *
 180       * Don't call this method directly.  Use DB::connect() instead.
 181       *
 182       * PEAR DB's mysql driver supports the following extra DSN options:
 183       *   + new_link      If set to true, causes subsequent calls to connect()
 184       *                    to return a new connection link instead of the
 185       *                    existing one.  WARNING: this is not portable to
 186       *                    other DBMS's. Available since PEAR DB 1.7.0.
 187       *   + client_flags  Any combination of MYSQL_CLIENT_* constants.
 188       *                    Only used if PHP is at version 4.3.0 or greater.
 189       *                    Available since PEAR DB 1.7.0.
 190       *
 191       * @param array $dsn         the data source name
 192       * @param bool  $persistent  should the connection be persistent?
 193       *
 194       * @return int  DB_OK on success. A DB_Error object on failure.
 195       */
 196      function connect($dsn, $persistent = false)
 197      {
 198          if (!PEAR::loadExtension('mysql')) {
 199              return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
 200          }
 201  
 202          $this->dsn = $dsn;
 203          if ($dsn['dbsyntax']) {
 204              $this->dbsyntax = $dsn['dbsyntax'];
 205          }
 206  
 207          $params = array();
 208          if ($dsn['protocol'] && $dsn['protocol'] == 'unix') {
 209              $params[0] = ':' . $dsn['socket'];
 210          } else {
 211              $params[0] = $dsn['hostspec'] ? $dsn['hostspec']
 212                           : 'localhost';
 213              if ($dsn['port']) {
 214                  $params[0] .= ':' . $dsn['port'];
 215              }
 216          }
 217          $params[] = $dsn['username'] ? $dsn['username'] : null;
 218          $params[] = $dsn['password'] ? $dsn['password'] : null;
 219  
 220          if (!$persistent) {
 221              if (isset($dsn['new_link'])
 222                  && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true))
 223              {
 224                  $params[] = true;
 225              } else {
 226                  $params[] = false;
 227              }
 228          }
 229          if (version_compare(phpversion(), '4.3.0', '>=')) {
 230              $params[] = isset($dsn['client_flags'])
 231                          ? $dsn['client_flags'] : null;
 232          }
 233  
 234          $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect';
 235  
 236          $ini = ini_get('track_errors');
 237          $php_errormsg = '';
 238          if ($ini) {
 239              $this->connection = @call_user_func_array($connect_function,
 240                                                        $params);
 241          } else {
 242              @ini_set('track_errors', 1);
 243              $this->connection = @call_user_func_array($connect_function,
 244                                                        $params);
 245              @ini_set('track_errors', $ini);
 246          }
 247  
 248          if (!$this->connection) {
 249              if (($err = @mysql_error()) != '') {
 250                  return $this->raiseError(DB_ERROR_CONNECT_FAILED,
 251                                           null, null, null, 
 252                                           $err);
 253              } else {
 254                  return $this->raiseError(DB_ERROR_CONNECT_FAILED,
 255                                           null, null, null,
 256                                           $php_errormsg);
 257              }
 258          }
 259  
 260          if ($dsn['database']) {
 261              if (!@mysql_select_db($dsn['database'], $this->connection)) {
 262                  return $this->mysqlRaiseError();
 263              }
 264              $this->_db = $dsn['database'];
 265          }
 266  
 267          return DB_OK;
 268      }
 269  
 270      // }}}
 271      // {{{ disconnect()
 272  
 273      /**
 274       * Disconnects from the database server
 275       *
 276       * @return bool  TRUE on success, FALSE on failure
 277       */
 278      function disconnect()
 279      {
 280          $ret = @mysql_close($this->connection);
 281          $this->connection = null;
 282          return $ret;
 283      }
 284  
 285      // }}}
 286      // {{{ simpleQuery()
 287  
 288      /**
 289       * Sends a query to the database server
 290       *
 291       * Generally uses mysql_query().  If you want to use
 292       * mysql_unbuffered_query() set the "result_buffering" option to 0 using
 293       * setOptions().  This option was added in Release 1.7.0.
 294       *
 295       * @param string  the SQL query string
 296       *
 297       * @return mixed  + a PHP result resrouce for successful SELECT queries
 298       *                + the DB_OK constant for other successful queries
 299       *                + a DB_Error object on failure
 300       */
 301      function simpleQuery($query)
 302      {
 303          $ismanip = $this->_checkManip($query);
 304          $this->last_query = $query;
 305          $query = $this->modifyQuery($query);
 306          if ($this->_db) {
 307              if (!@mysql_select_db($this->_db, $this->connection)) {
 308                  return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
 309              }
 310          }
 311          if (!$this->autocommit && $ismanip) {
 312              if ($this->transaction_opcount == 0) {
 313                  $result = @mysql_query('SET AUTOCOMMIT=0', $this->connection);
 314                  $result = @mysql_query('BEGIN', $this->connection);
 315                  if (!$result) {
 316                      return $this->mysqlRaiseError();
 317                  }
 318              }
 319              $this->transaction_opcount++;
 320          }
 321          if (!$this->options['result_buffering']) {
 322              $result = @mysql_unbuffered_query($query, $this->connection);
 323          } else {
 324              $result = @mysql_query($query, $this->connection);
 325          }
 326          if (!$result) {
 327              return $this->mysqlRaiseError();
 328          }
 329          if (is_resource($result)) {
 330              return $result;
 331          }
 332          return DB_OK;
 333      }
 334  
 335      // }}}
 336      // {{{ nextResult()
 337  
 338      /**
 339       * Move the internal mysql result pointer to the next available result
 340       *
 341       * This method has not been implemented yet.
 342       *
 343       * @param a valid sql result resource
 344       *
 345       * @return false
 346       */
 347      function nextResult($result)
 348      {
 349          return false;
 350      }
 351  
 352      // }}}
 353      // {{{ fetchInto()
 354  
 355      /**
 356       * Places a row from the result set into the given array
 357       *
 358       * Formating of the array and the data therein are configurable.
 359       * See DB_result::fetchInto() for more information.
 360       *
 361       * This method is not meant to be called directly.  Use
 362       * DB_result::fetchInto() instead.  It can't be declared "protected"
 363       * because DB_result is a separate object.
 364       *
 365       * @param resource $result    the query result resource
 366       * @param array    $arr       the referenced array to put the data in
 367       * @param int      $fetchmode how the resulting array should be indexed
 368       * @param int      $rownum    the row number to fetch (0 = first row)
 369       *
 370       * @return mixed  DB_OK on success, NULL when the end of a result set is
 371       *                 reached or on failure
 372       *
 373       * @see DB_result::fetchInto()
 374       */
 375      function fetchInto($result, &$arr, $fetchmode, $rownum = null)
 376      {
 377          if ($rownum !== null) {
 378              if (!@mysql_data_seek($result, $rownum)) {
 379                  return null;
 380              }
 381          }
 382          if ($fetchmode & DB_FETCHMODE_ASSOC) {
 383              $arr = @mysql_fetch_array($result, MYSQL_ASSOC);
 384              if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
 385                  $arr = array_change_key_case($arr, CASE_LOWER);
 386              }
 387          } else {
 388              $arr = @mysql_fetch_row($result);
 389          }
 390          if (!$arr) {
 391              return null;
 392          }
 393          if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
 394              /*
 395               * Even though this DBMS already trims output, we do this because
 396               * a field might have intentional whitespace at the end that
 397               * gets removed by DB_PORTABILITY_RTRIM under another driver.
 398               */
 399              $this->_rtrimArrayValues($arr);
 400          }
 401          if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
 402              $this->_convertNullArrayValuesToEmpty($arr);
 403          }
 404          return DB_OK;
 405      }
 406  
 407      // }}}
 408      // {{{ freeResult()
 409  
 410      /**
 411       * Deletes the result set and frees the memory occupied by the result set
 412       *
 413       * This method is not meant to be called directly.  Use
 414       * DB_result::free() instead.  It can't be declared "protected"
 415       * because DB_result is a separate object.
 416       *
 417       * @param resource $result  PHP's query result resource
 418       *
 419       * @return bool  TRUE on success, FALSE if $result is invalid
 420       *
 421       * @see DB_result::free()
 422       */
 423      function freeResult($result)
 424      {
 425          return is_resource($result) ? mysql_free_result($result) : false;
 426      }
 427  
 428      // }}}
 429      // {{{ numCols()
 430  
 431      /**
 432       * Gets the number of columns in a result set
 433       *
 434       * This method is not meant to be called directly.  Use
 435       * DB_result::numCols() instead.  It can't be declared "protected"
 436       * because DB_result is a separate object.
 437       *
 438       * @param resource $result  PHP's query result resource
 439       *
 440       * @return int  the number of columns.  A DB_Error object on failure.
 441       *
 442       * @see DB_result::numCols()
 443       */
 444      function numCols($result)
 445      {
 446          $cols = @mysql_num_fields($result);
 447          if (!$cols) {
 448              return $this->mysqlRaiseError();
 449          }
 450          return $cols;
 451      }
 452  
 453      // }}}
 454      // {{{ numRows()
 455  
 456      /**
 457       * Gets the number of rows in a result set
 458       *
 459       * This method is not meant to be called directly.  Use
 460       * DB_result::numRows() instead.  It can't be declared "protected"
 461       * because DB_result is a separate object.
 462       *
 463       * @param resource $result  PHP's query result resource
 464       *
 465       * @return int  the number of rows.  A DB_Error object on failure.
 466       *
 467       * @see DB_result::numRows()
 468       */
 469      function numRows($result)
 470      {
 471          $rows = @mysql_num_rows($result);
 472          if ($rows === null) {
 473              return $this->mysqlRaiseError();
 474          }
 475          return $rows;
 476      }
 477  
 478      // }}}
 479      // {{{ autoCommit()
 480  
 481      /**
 482       * Enables or disables automatic commits
 483       *
 484       * @param bool $onoff  true turns it on, false turns it off
 485       *
 486       * @return int  DB_OK on success.  A DB_Error object if the driver
 487       *               doesn't support auto-committing transactions.
 488       */
 489      function autoCommit($onoff = false)
 490      {
 491          // XXX if $this->transaction_opcount > 0, we should probably
 492          // issue a warning here.
 493          $this->autocommit = $onoff ? true : false;
 494          return DB_OK;
 495      }
 496  
 497      // }}}
 498      // {{{ commit()
 499  
 500      /**
 501       * Commits the current transaction
 502       *
 503       * @return int  DB_OK on success.  A DB_Error object on failure.
 504       */
 505      function commit()
 506      {
 507          if ($this->transaction_opcount > 0) {
 508              if ($this->_db) {
 509                  if (!@mysql_select_db($this->_db, $this->connection)) {
 510                      return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
 511                  }
 512              }
 513              $result = @mysql_query('COMMIT', $this->connection);
 514              $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
 515              $this->transaction_opcount = 0;
 516              if (!$result) {
 517                  return $this->mysqlRaiseError();
 518              }
 519          }
 520          return DB_OK;
 521      }
 522  
 523      // }}}
 524      // {{{ rollback()
 525  
 526      /**
 527       * Reverts the current transaction
 528       *
 529       * @return int  DB_OK on success.  A DB_Error object on failure.
 530       */
 531      function rollback()
 532      {
 533          if ($this->transaction_opcount > 0) {
 534              if ($this->_db) {
 535                  if (!@mysql_select_db($this->_db, $this->connection)) {
 536                      return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
 537                  }
 538              }
 539              $result = @mysql_query('ROLLBACK', $this->connection);
 540              $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
 541              $this->transaction_opcount = 0;
 542              if (!$result) {
 543                  return $this->mysqlRaiseError();
 544              }
 545          }
 546          return DB_OK;
 547      }
 548  
 549      // }}}
 550      // {{{ affectedRows()
 551  
 552      /**
 553       * Determines the number of rows affected by a data maniuplation query
 554       *
 555       * 0 is returned for queries that don't manipulate data.
 556       *
 557       * @return int  the number of rows.  A DB_Error object on failure.
 558       */
 559      function affectedRows()
 560      {
 561          if ($this->_last_query_manip) {
 562              return @mysql_affected_rows($this->connection);
 563          } else {
 564              return 0;
 565          }
 566       }
 567  
 568      // }}}
 569      // {{{ nextId()
 570  
 571      /**
 572       * Returns the next free id in a sequence
 573       *
 574       * @param string  $seq_name  name of the sequence
 575       * @param boolean $ondemand  when true, the seqence is automatically
 576       *                            created if it does not exist
 577       *
 578       * @return int  the next id number in the sequence.
 579       *               A DB_Error object on failure.
 580       *
 581       * @see DB_common::nextID(), DB_common::getSequenceName(),
 582       *      DB_mysql::createSequence(), DB_mysql::dropSequence()
 583       */
 584      function nextId($seq_name, $ondemand = true)
 585      {
 586          $seqname = $this->getSequenceName($seq_name);
 587          do {
 588              $repeat = 0;
 589              $this->pushErrorHandling(PEAR_ERROR_RETURN);
 590              $result = $this->query("UPDATE $seqname} ".
 591                                     'SET id=LAST_INSERT_ID(id+1)');
 592              $this->popErrorHandling();
 593              if ($result === DB_OK) {
 594                  // COMMON CASE
 595                  $id = @mysql_insert_id($this->connection);
 596                  if ($id != 0) {
 597                      return $id;
 598                  }
 599                  // EMPTY SEQ TABLE
 600                  // Sequence table must be empty for some reason, so fill
 601                  // it and return 1 and obtain a user-level lock
 602                  $result = $this->getOne("SELECT GET_LOCK('$seqname}_lock',10)");
 603                  if (DB::isError($result)) {
 604                      return $this->raiseError($result);
 605                  }
 606                  if ($result == 0) {
 607                      // Failed to get the lock
 608                      return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
 609                  }
 610  
 611                  // add the default value
 612                  $result = $this->query("REPLACE INTO $seqname} (id) VALUES (0)");
 613                  if (DB::isError($result)) {
 614                      return $this->raiseError($result);
 615                  }
 616  
 617                  // Release the lock
 618                  $result = $this->getOne('SELECT RELEASE_LOCK('
 619                                          . "'$seqname}_lock')");
 620                  if (DB::isError($result)) {
 621                      return $this->raiseError($result);
 622                  }
 623                  // We know what the result will be, so no need to try again
 624                  return 1;
 625  
 626              } elseif ($ondemand && DB::isError($result) &&
 627                  $result->getCode() == DB_ERROR_NOSUCHTABLE)
 628              {
 629                  // ONDEMAND TABLE CREATION
 630                  $result = $this->createSequence($seq_name);
 631                  if (DB::isError($result)) {
 632                      return $this->raiseError($result);
 633                  } else {
 634                      $repeat = 1;
 635                  }
 636  
 637              } elseif (DB::isError($result) &&
 638                        $result->getCode() == DB_ERROR_ALREADY_EXISTS)
 639              {
 640                  // BACKWARDS COMPAT
 641                  // see _BCsequence() comment
 642                  $result = $this->_BCsequence($seqname);
 643                  if (DB::isError($result)) {
 644                      return $this->raiseError($result);
 645                  }
 646                  $repeat = 1;
 647              }
 648          } while ($repeat);
 649  
 650          return $this->raiseError($result);
 651      }
 652  
 653      // }}}
 654      // {{{ createSequence()
 655  
 656      /**
 657       * Creates a new sequence
 658       *
 659       * @param string $seq_name  name of the new sequence
 660       *
 661       * @return int  DB_OK on success.  A DB_Error object on failure.
 662       *
 663       * @see DB_common::createSequence(), DB_common::getSequenceName(),
 664       *      DB_mysql::nextID(), DB_mysql::dropSequence()
 665       */
 666      function createSequence($seq_name)
 667      {
 668          $seqname = $this->getSequenceName($seq_name);
 669          $res = $this->query('CREATE TABLE ' . $seqname
 670                              . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'
 671                              . ' PRIMARY KEY(id))');
 672          if (DB::isError($res)) {
 673              return $res;
 674          }
 675          // insert yields value 1, nextId call will generate ID 2
 676          $res = $this->query("INSERT INTO $seqname} (id) VALUES (0)");
 677          if (DB::isError($res)) {
 678              return $res;
 679          }
 680          // so reset to zero
 681          return $this->query("UPDATE $seqname} SET id = 0");
 682      }
 683  
 684      // }}}
 685      // {{{ dropSequence()
 686  
 687      /**
 688       * Deletes a sequence
 689       *
 690       * @param string $seq_name  name of the sequence to be deleted
 691       *
 692       * @return int  DB_OK on success.  A DB_Error object on failure.
 693       *
 694       * @see DB_common::dropSequence(), DB_common::getSequenceName(),
 695       *      DB_mysql::nextID(), DB_mysql::createSequence()
 696       */
 697      function dropSequence($seq_name)
 698      {
 699          return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
 700      }
 701  
 702      // }}}
 703      // {{{ _BCsequence()
 704  
 705      /**
 706       * Backwards compatibility with old sequence emulation implementation
 707       * (clean up the dupes)
 708       *
 709       * @param string $seqname  the sequence name to clean up
 710       *
 711       * @return bool  true on success.  A DB_Error object on failure.
 712       *
 713       * @access private
 714       */
 715      function _BCsequence($seqname)
 716      {
 717          // Obtain a user-level lock... this will release any previous
 718          // application locks, but unlike LOCK TABLES, it does not abort
 719          // the current transaction and is much less frequently used.
 720          $result = $this->getOne("SELECT GET_LOCK('$seqname}_lock',10)");
 721          if (DB::isError($result)) {
 722              return $result;
 723          }
 724          if ($result == 0) {
 725              // Failed to get the lock, can't do the conversion, bail
 726              // with a DB_ERROR_NOT_LOCKED error
 727              return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
 728          }
 729  
 730          $highest_id = $this->getOne("SELECT MAX(id) FROM $seqname}");
 731          if (DB::isError($highest_id)) {
 732              return $highest_id;
 733          }
 734          // This should kill all rows except the highest
 735          // We should probably do something if $highest_id isn't
 736          // numeric, but I'm at a loss as how to handle that...
 737          $result = $this->query('DELETE FROM ' . $seqname
 738                                 . " WHERE id <> $highest_id");
 739          if (DB::isError($result)) {
 740              return $result;
 741          }
 742  
 743          // If another thread has been waiting for this lock,
 744          // it will go thru the above procedure, but will have no
 745          // real effect
 746          $result = $this->getOne("SELECT RELEASE_LOCK('$seqname}_lock')");
 747          if (DB::isError($result)) {
 748              return $result;
 749          }
 750          return true;
 751      }
 752  
 753      // }}}
 754      // {{{ quoteIdentifier()
 755  
 756      /**
 757       * Quotes a string so it can be safely used as a table or column name
 758       * (WARNING: using names that require this is a REALLY BAD IDEA)
 759       *
 760       * WARNING:  Older versions of MySQL can't handle the backtick
 761       * character (<kbd>`</kbd>) in table or column names.
 762       *
 763       * @param string $str  identifier name to be quoted
 764       *
 765       * @return string  quoted identifier string
 766       *
 767       * @see DB_common::quoteIdentifier()
 768       * @since Method available since Release 1.6.0
 769       */
 770      function quoteIdentifier($str)
 771      {
 772          return '`' . str_replace('`', '``', $str) . '`';
 773      }
 774  
 775      // }}}
 776      // {{{ quote()
 777  
 778      /**
 779       * @deprecated  Deprecated in release 1.6.0
 780       */
 781      function quote($str)
 782      {
 783          return $this->quoteSmart($str);
 784      }
 785  
 786      // }}}
 787      // {{{ escapeSimple()
 788  
 789      /**
 790       * Escapes a string according to the current DBMS's standards
 791       *
 792       * @param string $str  the string to be escaped
 793       *
 794       * @return string  the escaped string
 795       *
 796       * @see DB_common::quoteSmart()
 797       * @since Method available since Release 1.6.0
 798       */
 799      function escapeSimple($str)
 800      {
 801          if (function_exists('mysql_real_escape_string')) {
 802              return @mysql_real_escape_string($str, $this->connection);
 803          } else {
 804              return @mysql_escape_string($str);
 805          }
 806      }
 807  
 808      // }}}
 809      // {{{ modifyQuery()
 810  
 811      /**
 812       * Changes a query string for various DBMS specific reasons
 813       *
 814       * This little hack lets you know how many rows were deleted
 815       * when running a "DELETE FROM table" query.  Only implemented
 816       * if the DB_PORTABILITY_DELETE_COUNT portability option is on.
 817       *
 818       * @param string $query  the query string to modify
 819       *
 820       * @return string  the modified query string
 821       *
 822       * @access protected
 823       * @see DB_common::setOption()
 824       */
 825      function modifyQuery($query)
 826      {
 827          if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) {
 828              // "DELETE FROM table" gives 0 affected rows in MySQL.
 829              // This little hack lets you know how many rows were deleted.
 830              if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
 831                  $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
 832                                        'DELETE FROM \1 WHERE 1=1', $query);
 833              }
 834          }
 835          return $query;
 836      }
 837  
 838      // }}}
 839      // {{{ modifyLimitQuery()
 840  
 841      /**
 842       * Adds LIMIT clauses to a query string according to current DBMS standards
 843       *
 844       * @param string $query   the query to modify
 845       * @param int    $from    the row to start to fetching (0 = the first row)
 846       * @param int    $count   the numbers of rows to fetch
 847       * @param mixed  $params  array, string or numeric data to be used in
 848       *                         execution of the statement.  Quantity of items
 849       *                         passed must match quantity of placeholders in
 850       *                         query:  meaning 1 placeholder for non-array
 851       *                         parameters or 1 placeholder per array element.
 852       *
 853       * @return string  the query string with LIMIT clauses added
 854       *
 855       * @access protected
 856       */
 857      function modifyLimitQuery($query, $from, $count, $params = array())
 858      {
 859          if (DB::isManip($query) || $this->_next_query_manip) {
 860              return $query . " LIMIT $count";
 861          } else {
 862              return $query . " LIMIT $from, $count";
 863          }
 864      }
 865  
 866      // }}}
 867      // {{{ mysqlRaiseError()
 868  
 869      /**
 870       * Produces a DB_Error object regarding the current problem
 871       *
 872       * @param int $errno  if the error is being manually raised pass a
 873       *                     DB_ERROR* constant here.  If this isn't passed
 874       *                     the error information gathered from the DBMS.
 875       *
 876       * @return object  the DB_Error object
 877       *
 878       * @see DB_common::raiseError(),
 879       *      DB_mysql::errorNative(), DB_common::errorCode()
 880       */
 881      function mysqlRaiseError($errno = null)
 882      {
 883          if ($errno === null) {
 884              if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
 885                  $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT;
 886                  $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL;
 887                  $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT;
 888              } else {
 889                  // Doing this in case mode changes during runtime.
 890                  $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS;
 891                  $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT;
 892                  $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS;
 893              }
 894              $errno = $this->errorCode(mysql_errno($this->connection));
 895          }
 896          return $this->raiseError($errno, null, null, null,
 897                                   @mysql_errno($this->connection) . ' ** ' .
 898                                   @mysql_error($this->connection));
 899      }
 900  
 901      // }}}
 902      // {{{ errorNative()
 903  
 904      /**
 905       * Gets the DBMS' native error code produced by the last query
 906       *
 907       * @return int  the DBMS' error code
 908       */
 909      function errorNative()
 910      {
 911          return @mysql_errno($this->connection);
 912      }
 913  
 914      // }}}
 915      // {{{ tableInfo()
 916  
 917      /**
 918       * Returns information about a table or a result set
 919       *
 920       * @param object|string  $result  DB_result object from a query or a
 921       *                                 string containing the name of a table.
 922       *                                 While this also accepts a query result
 923       *                                 resource identifier, this behavior is
 924       *                                 deprecated.
 925       * @param int            $mode    a valid tableInfo mode
 926       *
 927       * @return array  an associative array with the information requested.
 928       *                 A DB_Error object on failure.
 929       *
 930       * @see DB_common::tableInfo()
 931       */
 932      function tableInfo($result, $mode = null)
 933      {
 934          if (is_string($result)) {
 935              /*
 936               * Probably received a table name.
 937               * Create a result resource identifier.
 938               */
 939              $id = @mysql_query("SELECT * FROM $result LIMIT 0",
 940                                 $this->connection);
 941              $got_string = true;
 942          } elseif (isset($result->result)) {
 943              /*
 944               * Probably received a result object.
 945               * Extract the result resource identifier.
 946               */
 947              $id = $result->result;
 948              $got_string = false;
 949          } else {
 950              /*
 951               * Probably received a result resource identifier.
 952               * Copy it.
 953               * Deprecated.  Here for compatibility only.
 954               */
 955              $id = $result;
 956              $got_string = false;
 957          }
 958  
 959          if (!is_resource($id)) {
 960              return $this->mysqlRaiseError(DB_ERROR_NEED_MORE_DATA);
 961          }
 962  
 963          if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
 964              $case_func = 'strtolower';
 965          } else {
 966              $case_func = 'strval';
 967          }
 968  
 969          $count = @mysql_num_fields($id);
 970          $res   = array();
 971  
 972          if ($mode) {
 973              $res['num_fields'] = $count;
 974          }
 975  
 976          for ($i = 0; $i < $count; $i++) {
 977              $res[$i] = array(
 978                  'table' => $case_func(@mysql_field_table($id, $i)),
 979                  'name'  => $case_func(@mysql_field_name($id, $i)),
 980                  'type'  => @mysql_field_type($id, $i),
 981                  'len'   => @mysql_field_len($id, $i),
 982                  'flags' => @mysql_field_flags($id, $i),
 983              );
 984              if ($mode & DB_TABLEINFO_ORDER) {
 985                  $res['order'][$res[$i]['name']] = $i;
 986              }
 987              if ($mode & DB_TABLEINFO_ORDERTABLE) {
 988                  $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
 989              }
 990          }
 991  
 992          // free the result only if we were called on a table
 993          if ($got_string) {
 994              @mysql_free_result($id);
 995          }
 996          return $res;
 997      }
 998  
 999      // }}}
1000      // {{{ getSpecialQuery()
1001  
1002      /**
1003       * Obtains the query string needed for listing a given type of objects
1004       *
1005       * @param string $type  the kind of objects you want to retrieve
1006       *
1007       * @return string  the SQL query string or null if the driver doesn't
1008       *                  support the object type requested
1009       *
1010       * @access protected
1011       * @see DB_common::getListOf()
1012       */
1013      function getSpecialQuery($type)
1014      {
1015          switch ($type) {
1016              case 'tables':
1017                  return 'SHOW TABLES';
1018              case 'users':
1019                  return 'SELECT DISTINCT User FROM mysql.user';
1020              case 'databases':
1021                  return 'SHOW DATABASES';
1022              default:
1023                  return null;
1024          }
1025      }
1026  
1027      // }}}
1028  
1029  }
1030  
1031  /*
1032   * Local variables:
1033   * tab-width: 4
1034   * c-basic-offset: 4
1035   * End:
1036   */
1037  
1038  ?>


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