Source for file mysql.php

Documentation is available at mysql.php

  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-2007 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.126 2007/09/21 13:32:52 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_PEAR_PATH.'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-2007 The PHP Group
  43.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  44.  * @version    Release: 1.7.13
  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.                                          nullnullnull
  252.                                          $err);
  253.             else {
  254.                 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
  255.                                          nullnullnull,
  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 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($resultMYSQL_ASSOC);
  384.             if ($this->options['portability'DB_PORTABILITY_LOWERCASE && $arr{
  385.                 $arr array_change_key_case($arrCASE_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($resultmysql_free_result($resultfalse;
  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[1022DB_ERROR_CONSTRAINT;
  886.                 $this->errorcode_map[1048DB_ERROR_CONSTRAINT_NOT_NULL;
  887.                 $this->errorcode_map[1062DB_ERROR_CONSTRAINT;
  888.             else {
  889.                 // Doing this in case mode changes during runtime.
  890.                 $this->errorcode_map[1022DB_ERROR_ALREADY_EXISTS;
  891.                 $this->errorcode_map[1048DB_ERROR_CONSTRAINT;
  892.                 $this->errorcode_map[1062DB_ERROR_ALREADY_EXISTS;
  893.             }
  894.             $errno $this->errorCode(mysql_errno($this->connection));
  895.         }
  896.         return $this->raiseError($errnonullnullnull,
  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.             // Fix for bug #11580.
  936.             if ($this->_db{
  937.                 if (!@mysql_select_db($this->_db$this->connection)) {
  938.                     return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
  939.                 }
  940.             }
  941.             
  942.             /*
  943.              * Probably received a table name.
  944.              * Create a result resource identifier.
  945.              */
  946.             $id @mysql_query("SELECT * FROM $result LIMIT 0",
  947.                                $this->connection);
  948.             $got_string true;
  949.         elseif (isset($result->result)) {
  950.             /*
  951.              * Probably received a result object.
  952.              * Extract the result resource identifier.
  953.              */
  954.             $id $result->result;
  955.             $got_string false;
  956.         else {
  957.             /*
  958.              * Probably received a result resource identifier.
  959.              * Copy it.
  960.              * Deprecated.  Here for compatibility only.
  961.              */
  962.             $id $result;
  963.             $got_string false;
  964.         }
  965.  
  966.         if (!is_resource($id)) {
  967.             return $this->mysqlRaiseError(DB_ERROR_NEED_MORE_DATA);
  968.         }
  969.  
  970.         if ($this->options['portability'DB_PORTABILITY_LOWERCASE{
  971.             $case_func 'strtolower';
  972.         else {
  973.             $case_func 'strval';
  974.         }
  975.  
  976.         $count @mysql_num_fields($id);
  977.         $res   array();
  978.  
  979.         if ($mode{
  980.             $res['num_fields'$count;
  981.         }
  982.  
  983.         for ($i 0$i $count$i++{
  984.             $res[$iarray(
  985.                 'table' => $case_func(@mysql_field_table($id$i)),
  986.                 'name'  => $case_func(@mysql_field_name($id$i)),
  987.                 'type'  => @mysql_field_type($id$i),
  988.                 'len'   => @mysql_field_len($id$i),
  989.                 'flags' => @mysql_field_flags($id$i),
  990.             );
  991.             if ($mode DB_TABLEINFO_ORDER{
  992.                 $res['order'][$res[$i]['name']] $i;
  993.             }
  994.             if ($mode DB_TABLEINFO_ORDERTABLE{
  995.                 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] $i;
  996.             }
  997.         }
  998.  
  999.         // free the result only if we were called on a table
  1000.         if ($got_string{
  1001.             @mysql_free_result($id);
  1002.         }
  1003.         return $res;
  1004.     }
  1005.  
  1006.     // }}}
  1007.     // {{{ getSpecialQuery()
  1008.  
  1009.     /**
  1010.      * Obtains the query string needed for listing a given type of objects
  1011.      *
  1012.      * @param string $type  the kind of objects you want to retrieve
  1013.      *
  1014.      * @return string  the SQL query string or null if the driver doesn't
  1015.      *                   support the object type requested
  1016.      *
  1017.      * @access protected
  1018.      * @see DB_common::getListOf()
  1019.      */
  1020.     function getSpecialQuery($type)
  1021.     {
  1022.         switch ($type{
  1023.             case 'tables':
  1024.                 return 'SHOW TABLES';
  1025.             case 'users':
  1026.                 return 'SELECT DISTINCT User FROM mysql.user';
  1027.             case 'databases':
  1028.                 return 'SHOW DATABASES';
  1029.             default:
  1030.                 return null;
  1031.         }
  1032.     }
  1033.  
  1034.     // }}}
  1035.  
  1036. }
  1037.  
  1038. /*
  1039.  * Local variables:
  1040.  * tab-width: 4
  1041.  * c-basic-offset: 4
  1042.  * End:
  1043.  */
  1044.  
  1045. ?>

Documentation generated on Wed, 09 Feb 2011 09:02:11 +0700 by phpDocumentor 1.4.2