DB
[ class tree: DB ] [ index: DB ] [ all elements ]

Source for file mysqli.php

Documentation is available at mysqli.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Author: Daniel Convissor <danielc@php.net>                           |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: mysqli.php,v 1.29 2004/04/29 23:40:54 danielc Exp $
  20.  
  21.  
  22. // EXPERIMENTAL
  23.  
  24.  
  25. require_once 'DB/common.php';
  26.  
  27. /**
  28.  * Database independent query interface definition for PHP's mysqli
  29.  * extension.
  30.  *
  31.  * This is for MySQL versions 4.1 and above.  Requires PHP 5.
  32.  *
  33.  * Note that persistent connections no longer exist.
  34.  *
  35.  * @package  DB
  36.  * @version  $Id: mysqli.php,v 1.29 2004/04/29 23:40:54 danielc Exp $
  37.  * @category Database
  38.  * @author   Daniel Convissor <danielc@php.net>
  39.  */
  40. class DB_mysqli extends DB_common
  41. {
  42.     // {{{ properties
  43.  
  44.     var $connection;
  45.     var $phptype$dbsyntax;
  46.     var $prepare_tokens = array();
  47.     var $prepare_types = array();
  48.     var $num_rows = array();
  49.     var $transaction_opcount = 0;
  50.     var $autocommit = true;
  51.     var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */
  52.     var $_db = false;
  53.  
  54.     // }}}
  55.     // {{{ constructor
  56.  
  57.     /**
  58.      * DB_mysql constructor.
  59.      *
  60.      * @access public
  61.      */
  62.     function DB_mysqli()
  63.     {
  64.         $this->DB_common();
  65.         $this->phptype = 'mysqli';
  66.         $this->dbsyntax = 'mysqli';
  67.         $this->features = array(
  68.             'prepare' => false,
  69.             'ssl' => true,
  70.             'transactions' => true,
  71.             'limit' => 'alter'
  72.         );
  73.         $this->errorcode_map = array(
  74.             1004 => DB_ERROR_CANNOT_CREATE,
  75.             1005 => DB_ERROR_CANNOT_CREATE,
  76.             1006 => DB_ERROR_CANNOT_CREATE,
  77.             1007 => DB_ERROR_ALREADY_EXISTS,
  78.             1008 => DB_ERROR_CANNOT_DROP,
  79.             1022 => DB_ERROR_ALREADY_EXISTS,
  80.             1046 => DB_ERROR_NODBSELECTED,
  81.             1048 => DB_ERROR_CONSTRAINT,
  82.             1050 => DB_ERROR_ALREADY_EXISTS,
  83.             1051 => DB_ERROR_NOSUCHTABLE,
  84.             1054 => DB_ERROR_NOSUCHFIELD,
  85.             1062 => DB_ERROR_ALREADY_EXISTS,
  86.             1064 => DB_ERROR_SYNTAX,
  87.             1100 => DB_ERROR_NOT_LOCKED,
  88.             1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
  89.             1146 => DB_ERROR_NOSUCHTABLE,
  90.             1216 => DB_ERROR_CONSTRAINT,
  91.             1217 => DB_ERROR_CONSTRAINT,
  92.         );
  93.     }
  94.  
  95.     // }}}
  96.     // {{{ connect()
  97.  
  98.     /**
  99.      * Connect to a database and log in as the specified user.
  100.      *
  101.      * @param string $dsn the data source name (see DB::parseDSN for syntax)
  102.      * @param boolean $persistent (optional) whether the connection should
  103.      *                             be persistent
  104.      * @return mixed DB_OK on success, a DB error on failure
  105.      * @access public
  106.      */
  107.     function connect($dsninfo$persistent = false)
  108.     {
  109.         if (!DB::assertExtension('mysqli')) {
  110.             return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  111.         }
  112.  
  113.         $this->dsn $dsninfo;
  114.         $conn      = false;
  115.         @ini_set('track_errors'true);
  116.  
  117.         if ($this->getOption('ssl'=== true{
  118.             $init mysqli_init();
  119.             mysqli_ssl_set(
  120.                 $init,
  121.                 empty($dsninfo['key'])    ? null : $dsninfo['key'],
  122.                 empty($dsninfo['cert'])   ? null : $dsninfo['cert'],
  123.                 empty($dsninfo['ca'])     ? null : $dsninfo['ca'],
  124.                 empty($dsninfo['capath']? null : $dsninfo['capath'],
  125.                 empty($dsninfo['cipher']? null : $dsninfo['cipher']
  126.             );
  127.             if ($conn @mysqli_real_connect($init,
  128.                                              $dsninfo['hostspec'],
  129.                                              $dsninfo['username'],
  130.                                              $dsninfo['password'],
  131.                                              $dsninfo['database'],
  132.                                              $dsninfo['port'],
  133.                                              $dsninfo['socket']))
  134.             {
  135.                 $conn $init;
  136.             }
  137.         else {
  138.             $conn @mysqli_connect(
  139.                 $dsninfo['hostspec'],
  140.                 $dsninfo['username'],
  141.                 $dsninfo['password'],
  142.                 $dsninfo['database'],
  143.                 $dsninfo['port'],
  144.                 $dsninfo['socket']
  145.             );
  146.         }
  147.  
  148.         @ini_restore('track_errors');
  149.  
  150.         if (!$conn{
  151.             if (($err @mysqli_connect_error()) != ''{
  152.                 return $this->raiseError(DB_ERROR_CONNECT_FAILEDnullnull,
  153.                                          null$err);
  154.             elseif (empty($php_errormsg)) {
  155.                 return $this->raiseError(DB_ERROR_CONNECT_FAILED);
  156.             else {
  157.                 return $this->raiseError(DB_ERROR_CONNECT_FAILEDnullnull,
  158.                                          null$php_errormsg);
  159.             }
  160.         }
  161.  
  162.         if ($dsninfo['database']{
  163.             $this->_db $dsninfo['database'];
  164.         }
  165.  
  166.         $this->connection = $conn;
  167.         return DB_OK;
  168.     }
  169.  
  170.     // }}}
  171.     // {{{ disconnect()
  172.  
  173.     /**
  174.      * Log out and disconnect from the database.
  175.      *
  176.      * @return boolean true on success, false if not connected
  177.      * @access public
  178.      */
  179.     function disconnect()
  180.     {
  181.         $ret @mysqli_close($this->connection);
  182.         $this->connection = null;
  183.         return $ret;
  184.     }
  185.  
  186.     // }}}
  187.     // {{{ simpleQuery()
  188.  
  189.     /**
  190.      * Send a query to MySQL and return the results as a MySQL resource
  191.      * identifier.
  192.      *
  193.      * @param string $query the SQL query
  194.      * @return mixed a valid MySQL result for successful SELECT
  195.      *                queries, DB_OK for other successful queries.
  196.      *                A DB error is returned on failure.
  197.      * @access public
  198.      */
  199.     function simpleQuery($query)
  200.     {
  201.         $ismanip DB::isManip($query);
  202.         $this->last_query = $query;
  203.         $query $this->modifyQuery($query);
  204.         if ($this->_db{
  205.             if (!@mysqli_select_db($this->connection$this->_db)) {
  206.                 return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
  207.             }
  208.         }
  209.         if (!$this->autocommit && $ismanip{
  210.             if ($this->transaction_opcount == 0{
  211.                 $result @mysqli_query($this->connection'SET AUTOCOMMIT=0');
  212.                 $result @mysqli_query($this->connection'BEGIN');
  213.                 if (!$result{
  214.                     return $this->mysqlRaiseError();
  215.                 }
  216.             }
  217.             $this->transaction_opcount++;
  218.         }
  219.         $result @mysqli_query($this->connection$query);
  220.         if (!$result{
  221.             return $this->mysqlRaiseError();
  222.         }
  223. # this next block is still sketchy..
  224.         if (is_object($result)) {
  225.             $numrows $this->numrows($result);
  226.             if (is_object($numrows)) {
  227.                 return $numrows;
  228.             }
  229. # need to come up with different means for next line
  230. # since $result is object (int)$result won't fly...
  231. //            $this->num_rows[(int)$result] = $numrows;
  232.             return $result;
  233.         }
  234.         return DB_OK;
  235.     }
  236.  
  237.     // }}}
  238.     // {{{ nextResult()
  239.  
  240.     /**
  241.      * Move the internal mysql result pointer to the next available result.
  242.      *
  243.      * This method has not been implemented yet.
  244.      *
  245.      * @param resource $result a valid sql result resource
  246.      * @return false 
  247.      * @access public
  248.      */
  249.     function nextResult($result)
  250.     {
  251.         return false;
  252.     }
  253.  
  254.     // }}}
  255.     // {{{ fetchInto()
  256.  
  257.     /**
  258.      * Fetch a row and insert the data into an existing array.
  259.      *
  260.      * Formating of the array and the data therein are configurable.
  261.      * See DB_result::fetchInto() for more information.
  262.      *
  263.      * @param resource $result    query result identifier
  264.      * @param array    $arr       (reference) array where data from the row
  265.      *                             should be placed
  266.      * @param int      $fetchmode how the resulting array should be indexed
  267.      * @param int      $rownum    the row number to fetch
  268.      *
  269.      * @return mixed DB_OK on success, null when end of result set is
  270.      *                reached or on failure
  271.      *
  272.      * @see DB_result::fetchInto()
  273.      * @access private
  274.      */
  275.     function fetchInto($result&$arr$fetchmode$rownum=null)
  276.     {
  277.         if ($rownum !== null{
  278.             if (!@mysqli_data_seek($result$rownum)) {
  279.                 return null;
  280.             }
  281.         }
  282.         if ($fetchmode DB_FETCHMODE_ASSOC{
  283.             $arr @mysqli_fetch_array($resultMYSQLI_ASSOC);
  284.             if ($this->options['portability'DB_PORTABILITY_LOWERCASE && $arr{
  285.                 $arr array_change_key_case($arrCASE_LOWER);
  286.             }
  287.         else {
  288.             $arr @mysqli_fetch_row($result);
  289.         }
  290.         if (!$arr{
  291.             $errno @mysqli_errno($this->connection);
  292.             if (!$errno{
  293.                 return null;
  294.             }
  295.             return $this->mysqlRaiseError($errno);
  296.         }
  297.         if ($this->options['portability'DB_PORTABILITY_RTRIM{
  298.             /*
  299.              * Even though this DBMS already trims output, we do this because
  300.              * a field might have intentional whitespace at the end that
  301.              * gets removed by DB_PORTABILITY_RTRIM under another driver.
  302.              */
  303.             $this->_rtrimArrayValues($arr);
  304.         }
  305.         if ($this->options['portability'DB_PORTABILITY_NULL_TO_EMPTY{
  306.             $this->_convertNullArrayValuesToEmpty($arr);
  307.         }
  308.         return DB_OK;
  309.     }
  310.  
  311.     // }}}
  312.     // {{{ freeResult()
  313.  
  314.     /**
  315.      * Free the internal resources associated with $result.
  316.      *
  317.      * @param resource $result MySQL result identifier
  318.      * @return bool true on success, false if $result is invalid
  319.      * @access public
  320.      */
  321.     function freeResult($result)
  322.     {
  323. # need to come up with different means for next line
  324. # since $result is object (int)$result won't fly...
  325. //        unset($this->num_rows[(int)$result]);
  326.         return @mysqli_free_result($result);
  327.     }
  328.  
  329.     // }}}
  330.     // {{{ numCols()
  331.  
  332.     /**
  333.      * Get the number of columns in a result set.
  334.      *
  335.      * @param $result MySQL result identifier
  336.      *
  337.      * @access public
  338.      *
  339.      * @return int the number of columns per row in $result
  340.      */
  341.     function numCols($result)
  342.     {
  343.         $cols @mysqli_num_fields($result);
  344.  
  345.         if (!$cols{
  346.             return $this->mysqlRaiseError();
  347.         }
  348.  
  349.         return $cols;
  350.     }
  351.  
  352.     // }}}
  353.     // {{{ numRows()
  354.  
  355.     /**
  356.      * Get the number of rows in a result set.
  357.      *
  358.      * @param resource $result MySQL result identifier
  359.      * @return int the number of rows in $result
  360.      * @access public
  361.      */
  362.     function numRows($result)
  363.     {
  364.         $rows @mysqli_num_rows($result);
  365.         if ($rows === null{
  366.             return $this->mysqlRaiseError();
  367.         }
  368.         return $rows;
  369.     }
  370.  
  371.     // }}}
  372.     // {{{ autoCommit()
  373.  
  374.     /**
  375.      * Enable/disable automatic commits.
  376.      */
  377.     function autoCommit($onoff = false)
  378.     {
  379.         // XXX if $this->transaction_opcount > 0, we should probably
  380.         // issue a warning here.
  381.         $this->autocommit = $onoff ? true : false;
  382.         return DB_OK;
  383.     }
  384.  
  385.     // }}}
  386.     // {{{ commit()
  387.  
  388.     /**
  389.      * Commit the current transaction.
  390.      */
  391.     function commit()
  392.     {
  393.         if ($this->transaction_opcount > 0{
  394.             if ($this->_db{
  395.                 if (!@mysqli_select_db($this->connection$this->_db)) {
  396.                     return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
  397.                 }
  398.             }
  399.             $result @mysqli_query($this->connection'COMMIT');
  400.             $result @mysqli_query($this->connection'SET AUTOCOMMIT=1');
  401.             $this->transaction_opcount = 0;
  402.             if (!$result{
  403.                 return $this->mysqlRaiseError();
  404.             }
  405.         }
  406.         return DB_OK;
  407.     }
  408.  
  409.     // }}}
  410.     // {{{ rollback()
  411.  
  412.     /**
  413.      * Roll back (undo) the current transaction.
  414.      */
  415.     function rollback()
  416.     {
  417.         if ($this->transaction_opcount > 0{
  418.             if ($this->_db{
  419.                 if (!@mysqli_select_db($this->connection$this->_db)) {
  420.                     return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
  421.                 }
  422.             }
  423.             $result @mysqli_query($this->connection'ROLLBACK');
  424.             $result @mysqli_query($this->connection'SET AUTOCOMMIT=1');
  425.             $this->transaction_opcount = 0;
  426.             if (!$result{
  427.                 return $this->mysqlRaiseError();
  428.             }
  429.         }
  430.         return DB_OK;
  431.     }
  432.  
  433.     // }}}
  434.     // {{{ affectedRows()
  435.  
  436.     /**
  437.      * Gets the number of rows affected by the data manipulation
  438.      * query.  For other queries, this function returns 0.
  439.      *
  440.      * @return integer number of rows affected by the last query
  441.      */
  442.     function affectedRows()
  443.     {
  444.         if (DB::isManip($this->last_query)) {
  445.             return @mysqli_affected_rows($this->connection);
  446.         else {
  447.             return 0;
  448.         }
  449.      }
  450.  
  451.     // }}}
  452.     // {{{ errorNative()
  453.  
  454.     /**
  455.      * Get the native error code of the last error (if any) that
  456.      * occured on the current connection.
  457.      *
  458.      * @return int native MySQL error code
  459.      * @access public
  460.      */
  461.     function errorNative()
  462.     {
  463.         return @mysqli_errno($this->connection);
  464.     }
  465.  
  466.     // }}}
  467.     // {{{ nextId()
  468.  
  469.     /**
  470.      * Returns the next free id in a sequence
  471.      *
  472.      * @param string  $seq_name  name of the sequence
  473.      * @param boolean $ondemand  when true, the seqence is automatically
  474.      *                            created if it does not exist
  475.      *
  476.      * @return int  the next id number in the sequence.  DB_Error if problem.
  477.      *
  478.      * @internal
  479.      * @see DB_common::nextID()
  480.      * @access public
  481.      */
  482.     function nextId($seq_name$ondemand = true)
  483.     {
  484.         $seqname $this->getSequenceName($seq_name);
  485.         do {
  486.             $repeat = 0;
  487.             $this->pushErrorHandling(PEAR_ERROR_RETURN);
  488.             $result $this->query("UPDATE ${seqname} ".
  489.                                    'SET id=LAST_INSERT_ID(id+1)');
  490.             $this->popErrorHandling();
  491.             if ($result === DB_OK{
  492.                 /** COMMON CASE **/
  493.                 $id @mysqli_insert_id($this->connection);
  494.                 if ($id != 0{
  495.                     return $id;
  496.                 }
  497.                 /** EMPTY SEQ TABLE **/
  498.                 // Sequence table must be empty for some reason, so fill it and return 1
  499.                 // Obtain a user-level lock
  500.                 $result $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
  501.                 if (DB::isError($result)) {
  502.                     return $this->raiseError($result);
  503.                 }
  504.                 if ($result == 0{
  505.                     // Failed to get the lock, bail with a DB_ERROR_NOT_LOCKED error
  506.                     return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
  507.                 }
  508.  
  509.                 // add the default value
  510.                 $result $this->query("REPLACE INTO ${seqname} (id) VALUES (0)");
  511.                 if (DB::isError($result)) {
  512.                     return $this->raiseError($result);
  513.                 }
  514.  
  515.                 // Release the lock
  516.                 $result $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
  517.                 if (DB::isError($result)) {
  518.                     return $this->raiseError($result);
  519.                 }
  520.                 // We know what the result will be, so no need to try again
  521.                 return 1;
  522.  
  523.             /** ONDEMAND TABLE CREATION **/
  524.             elseif ($ondemand && DB::isError($result&&
  525.                 $result->getCode(== DB_ERROR_NOSUCHTABLE)
  526.             {
  527.                 $result $this->createSequence($seq_name);
  528.                 // Since createSequence initializes the ID to be 1,
  529.                 // we do not need to retrieve the ID again (or we will get 2)
  530.                 if (DB::isError($result)) {
  531.                     return $this->raiseError($result);
  532.                 else {
  533.                     // First ID of a newly created sequence is 1
  534.                     return 1;
  535.                 }
  536.  
  537.             /** BACKWARDS COMPAT **/
  538.             elseif (DB::isError($result&&
  539.                       $result->getCode(== DB_ERROR_ALREADY_EXISTS)
  540.             {
  541.                 // see _BCsequence() comment
  542.                 $result $this->_BCsequence($seqname);
  543.                 if (DB::isError($result)) {
  544.                     return $this->raiseError($result);
  545.                 }
  546.                 $repeat = 1;
  547.             }
  548.         while ($repeat);
  549.  
  550.         return $this->raiseError($result);
  551.     }
  552.  
  553.     /**
  554.      * Creates a new sequence
  555.      *
  556.      * @param string $seq_name  name of the new sequence
  557.      *
  558.      * @return int  DB_OK on success.  A DB_Error object is returned if
  559.      *               problems arise.
  560.      *
  561.      * @internal
  562.      * @see DB_common::createSequence()
  563.      * @access public
  564.      */
  565.     function createSequence($seq_name)
  566.     {
  567.         $seqname $this->getSequenceName($seq_name);
  568.         $res $this->query("CREATE TABLE ${seqname} ".
  569.                             '(id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'.
  570.                             ' PRIMARY KEY(id))');
  571.         if (DB::isError($res)) {
  572.             return $res;
  573.         }
  574.         // insert yields value 1, nextId call will generate ID 2
  575.         return $this->query("INSERT INTO ${seqname} (id) VALUES (0)");
  576.     }
  577.  
  578.     // }}}
  579.     // {{{ dropSequence()
  580.  
  581.     /**
  582.      * Deletes a sequence
  583.      *
  584.      * @param string $seq_name  name of the sequence to be deleted
  585.      *
  586.      * @return int  DB_OK on success.  DB_Error if problems.
  587.      *
  588.      * @internal
  589.      * @see DB_common::dropSequence()
  590.      * @access public
  591.      */
  592.     function dropSequence($seq_name)
  593.     {
  594.         return $this->query('DROP TABLE ' $this->getSequenceName($seq_name));
  595.     }
  596.  
  597.     // }}}
  598.     // {{{ _BCsequence()
  599.  
  600.     /**
  601.      * Backwards compatibility with old sequence emulation implementation
  602.      * (clean up the dupes).
  603.      *
  604.      * @param string $seqname The sequence name to clean up
  605.      * @return mixed DB_Error or true
  606.      */
  607.     function _BCsequence($seqname)
  608.     {
  609.         // Obtain a user-level lock... this will release any previous
  610.         // application locks, but unlike LOCK TABLES, it does not abort
  611.         // the current transaction and is much less frequently used.
  612.         $result $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
  613.         if (DB::isError($result)) {
  614.             return $result;
  615.         }
  616.         if ($result == 0{
  617.             // Failed to get the lock, can't do the conversion, bail
  618.             // with a DB_ERROR_NOT_LOCKED error
  619.             return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
  620.         }
  621.  
  622.         $highest_id $this->getOne("SELECT MAX(id) FROM ${seqname}");
  623.         if (DB::isError($highest_id)) {
  624.             return $highest_id;
  625.         }
  626.         // This should kill all rows except the highest
  627.         // We should probably do something if $highest_id isn't
  628.         // numeric, but I'm at a loss as how to handle that...
  629.         $result $this->query("DELETE FROM ${seqname} WHERE id <> $highest_id");
  630.         if (DB::isError($result)) {
  631.             return $result;
  632.         }
  633.  
  634.         // If another thread has been waiting for this lock,
  635.         // it will go thru the above procedure, but will have no
  636.         // real effect
  637.         $result $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
  638.         if (DB::isError($result)) {
  639.             return $result;
  640.         }
  641.         return true;
  642.     }
  643.  
  644.     // }}}
  645.     // {{{ quoteIdentifier()
  646.  
  647.     /**
  648.      * Quote a string so it can be safely used as a table or column name
  649.      *
  650.      * Quoting style depends on which database driver is being used.
  651.      *
  652.      * MySQL can't handle the backtick character (<kbd>`</kbd>) in
  653.      * table or column names.
  654.      *
  655.      * @param string $str  identifier name to be quoted
  656.      *
  657.      * @return string  quoted identifier string
  658.      *
  659.      * @since 1.6.0
  660.      * @access public
  661.      * @internal
  662.      */
  663.     function quoteIdentifier($str)
  664.     {
  665.         return '`' $str '`';
  666.     }
  667.  
  668.     // }}}
  669.     // {{{ escapeSimple()
  670.  
  671.     /**
  672.      * Escape a string according to the current DBMS's standards
  673.      *
  674.      * @param string $str  the string to be escaped
  675.      *
  676.      * @return string  the escaped string
  677.      *
  678.      * @internal
  679.      */
  680.     function escapeSimple($str{
  681.         return @mysqli_real_escape_string($this->connection$str);
  682.     }
  683.  
  684.     // }}}
  685.     // {{{ modifyQuery()
  686.  
  687.     function modifyQuery($query)
  688.     {
  689.         if ($this->options['portability'DB_PORTABILITY_DELETE_COUNT{
  690.             // "DELETE FROM table" gives 0 affected rows in MySQL.
  691.             // This little hack lets you know how many rows were deleted.
  692.             if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i'$query)) {
  693.                 $query preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
  694.                                       'DELETE FROM \1 WHERE 1=1'$query);
  695.             }
  696.         }
  697.         return $query;
  698.     }
  699.  
  700.     // }}}
  701.     // {{{ modifyLimitQuery()
  702.  
  703.     function modifyLimitQuery($query$from$count$params = array())
  704.     {
  705.         if (DB::isManip($query)) {
  706.             return $query . " LIMIT $count";
  707.         else {
  708.             return $query . " LIMIT $from$count";
  709.         }
  710.     }
  711.  
  712.     // }}}
  713.     // {{{ mysqlRaiseError()
  714.  
  715.     /**
  716.      * Gather information about an error, then use that info to create a
  717.      * DB error object and finally return that object.
  718.      *
  719.      * @param  integer  $errno  PEAR error number (usually a DB constant) if
  720.      *                           manually raising an error
  721.      * @return object  DB error object
  722.      * @see DB_common::errorCode()
  723.      * @see DB_common::raiseError()
  724.      */
  725.     function mysqlRaiseError($errno = null)
  726.     {
  727.         if ($errno === null{
  728.             if ($this->options['portability'DB_PORTABILITY_ERRORS{
  729.                 $this->errorcode_map[1022DB_ERROR_CONSTRAINT;
  730.                 $this->errorcode_map[1048DB_ERROR_CONSTRAINT_NOT_NULL;
  731.                 $this->errorcode_map[1062DB_ERROR_CONSTRAINT;
  732.             else {
  733.                 // Doing this in case mode changes during runtime.
  734.                 $this->errorcode_map[1022DB_ERROR_ALREADY_EXISTS;
  735.                 $this->errorcode_map[1048DB_ERROR_CONSTRAINT;
  736.                 $this->errorcode_map[1062DB_ERROR_ALREADY_EXISTS;
  737.             }
  738.             $errno $this->errorCode(mysqli_errno($this->connection));
  739.         }
  740.         return $this->raiseError($errnonullnullnull,
  741.                                  @mysqli_errno($this->connection' ** ' .
  742.                                  @mysqli_error($this->connection));
  743.     }
  744.  
  745.     // }}}
  746.     // {{{ tableInfo()
  747.  
  748.     /**
  749.      * Returns information about a table or a result set.
  750.      *
  751.      * WARNING: this method will probably not work because the mysqli_*()
  752.      * functions it relies upon may not exist.
  753.      *
  754.      * @param object|string $result  DB_result object from a query or a
  755.      *                                 string containing the name of a table
  756.      * @param int            $mode    a valid tableInfo mode
  757.      * @return array  an associative array with the information requested
  758.      *                 or an error object if something is wrong
  759.      * @access public
  760.      * @internal
  761.      * @see DB_common::tableInfo()
  762.      */
  763.     function tableInfo($result$mode = null{
  764.         if (isset($result->result)) {
  765.             /*
  766.              * Probably received a result object.
  767.              * Extract the result resource identifier.
  768.              */
  769.             $id $result->result;
  770.             $got_string = false;
  771.         elseif (is_string($result)) {
  772.             /*
  773.              * Probably received a table name.
  774.              * Create a result resource identifier.
  775.              */
  776.             $id @mysqli_query($this->connection,
  777.                                 "SELECT * FROM $result LIMIT 0");
  778.             $got_string = true;
  779.         else {
  780.             /*
  781.              * Probably received a result resource identifier.
  782.              * Copy it.
  783.              * Deprecated.  Here for compatibility only.
  784.              */
  785.             $id $result;
  786.             $got_string = false;
  787.         }
  788.  
  789.         if (!is_a($id'mysqli_result')) {
  790.             return $this->mysqlRaiseError(DB_ERROR_NEED_MORE_DATA);
  791.         }
  792.  
  793.         if ($this->options['portability'DB_PORTABILITY_LOWERCASE{
  794.             $case_func 'strtolower';
  795.         else {
  796.             $case_func 'strval';
  797.         }
  798.  
  799.         $count @mysqli_num_fields($id);
  800.  
  801.         // made this IF due to performance (one if is faster than $count if's)
  802.         if (!$mode{
  803.             for ($i=0; $i<$count$i++{
  804.                 $tmp @mysqli_fetch_field($id);
  805.                 $res[$i]['table'$case_func($tmp->table);
  806.                 $res[$i]['name']  $case_func($tmp->name);
  807.                 $res[$i]['type']  $tmp->type;
  808.                 $res[$i]['len']   $tmp->max_length;
  809.  
  810.                 $res[$i]['flags''';
  811.                 if ($tmp->flags MYSQLI_NOT_NULL_FLAG{
  812.                     $res[$i]['flags'.= 'not_null ';
  813.                 }
  814.                 if ($tmp->flags MYSQLI_PRI_KEY_FLAG{
  815.                     $res[$i]['flags'.= 'primary_key ';
  816.                 }
  817.                 if ($tmp->flags MYSQLI_UNIQUE_KEY_FLAG{
  818.                     $res[$i]['flags'.= 'unique_key ';
  819.                 }
  820.                 if ($tmp->flags MYSQLI_MULTIPLE_KEY_FLAG{
  821.                     $res[$i]['flags'.= 'multiple_key ';
  822.                 }
  823.                 if ($tmp->flags MYSQLI_BLOB_FLAG{
  824.                     $res[$i]['flags'.= 'blob ';
  825.                 }
  826.                 if ($tmp->def{
  827.                     $res[$i]['flags'.= 'default_' rawurlencode($tmp->def);
  828.                 }
  829.                 $res[$i]['flags'trim($res[$i]['flags']);
  830.             }
  831.         else // full
  832.             $res['num_fields']$count;
  833.  
  834.             for ($i=0; $i<$count$i++{
  835.                 $tmp @mysqli_fetch_field($id);
  836.                 $res[$i]['table'$case_func($tmp->table);
  837.                 $res[$i]['name']  $case_func($tmp->name);
  838.                 $res[$i]['type']  $tmp->type;
  839.                 $res[$i]['len']   $tmp->max_length;
  840.  
  841.                 $res[$i]['flags''';
  842.                 if ($tmp->flags MYSQLI_NOT_NULL_FLAG{
  843.                     $res[$i]['flags'.= 'not_null ';
  844.                 }
  845.                 if ($tmp->flags MYSQLI_PRI_KEY_FLAG{
  846.                     $res[$i]['flags'.= 'primary_key ';
  847.                 }
  848.                 if ($tmp->flags MYSQLI_UNIQUE_KEY_FLAG{
  849.                     $res[$i]['flags'.= 'unique_key ';
  850.                 }
  851.                 if ($tmp->flags MYSQLI_MULTIPLE_KEY_FLAG{
  852.                     $res[$i]['flags'.= 'multiple_key ';
  853.                 }
  854.                 if ($tmp->flags MYSQLI_BLOB_FLAG{
  855.                     $res[$i]['flags'.= 'blob ';
  856.                 }
  857.                 if ($tmp->def{
  858.                     $res[$i]['flags'.= 'default_' rawurlencode($tmp->def);
  859.                 }
  860.                 $res[$i]['flags'trim($res[$i]['flags']);
  861.  
  862.                 if ($mode DB_TABLEINFO_ORDER{
  863.                     $res['order'][$res[$i]['name']] $i;
  864.                 }
  865.                 if ($mode DB_TABLEINFO_ORDERTABLE{
  866.                     $res['ordertable'][$res[$i]['table']][$res[$i]['name']] $i;
  867.                 }
  868.             }
  869.         }
  870.  
  871.         // free the result only if we were called on a table
  872.         if ($got_string{
  873.             @mysqli_free_result($id);
  874.         }
  875.         return $res;
  876.     }
  877.  
  878.     // }}}
  879.     // {{{ getSpecialQuery()
  880.  
  881.     /**
  882.      * Returns the query needed to get some backend info.
  883.      *
  884.      * @param string $type What kind of info you want to retrieve
  885.      * @return string The SQL query string
  886.      */
  887.     function getSpecialQuery($type)
  888.     {
  889.         switch ($type{
  890.             case 'tables':
  891.                 return 'SHOW TABLES';
  892.             case 'views':
  893.                 return DB_ERROR_NOT_CAPABLE;
  894.             case 'users':
  895.                 $sql 'select distinct User from user';
  896.                 if ($this->dsn['database'!= 'mysql'{
  897.                     $dsn $this->dsn;
  898.                     $dsn['database''mysql';
  899.                     if (DB::isError($db DB::connect($dsn))) {
  900.                         return $db;
  901.                     }
  902.                     $sql $db->getCol($sql);
  903.                     $db->disconnect();
  904.                     // XXX Fixme the mysql driver should take care of this
  905.                     if (!@mysqli_select_db($this->connection$this->dsn['database'])) {
  906.                         return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
  907.                     }
  908.                 }
  909.                 return $sql;
  910.             case 'databases':
  911.                 return 'SHOW DATABASES';
  912.             default:
  913.                 return null;
  914.         }
  915.     }
  916.  
  917.    // }}}
  918.  
  919. }
  920.  
  921. /*
  922.  * Local variables:
  923.  * tab-width: 4
  924.  * c-basic-offset: 4
  925.  * End:
  926.  */
  927.  
  928. ?>

Documentation generated on Mon, 11 Mar 2019 10:16:28 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.