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

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