[ PHPXref.com ] [ Generated: Sun Jul 20 20:47:21 2008 ] [ TPLN 2.6 ]
[ Index ]     [ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

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


[ Powered by PHPXref - Served by Debian GNU/Linux ]