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

Source for file mysql.php

Documentation is available at mysql.php

  1. <?php
  2. // vim: set et ts=4 sw=4 fdm=marker:
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  7. // | Stig. S. Bakken, Lukas Smith                                         |
  8. // | All rights reserved.                                                 |
  9. // +----------------------------------------------------------------------+
  10. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
  11. // | API as well as database abstraction for PHP applications.            |
  12. // | This LICENSE is in the BSD license style.                            |
  13. // |                                                                      |
  14. // | Redistribution and use in source and binary forms, with or without   |
  15. // | modification, are permitted provided that the following conditions   |
  16. // | are met:                                                             |
  17. // |                                                                      |
  18. // | Redistributions of source code must retain the above copyright       |
  19. // | notice, this list of conditions and the following disclaimer.        |
  20. // |                                                                      |
  21. // | Redistributions in binary form must reproduce the above copyright    |
  22. // | notice, this list of conditions and the following disclaimer in the  |
  23. // | documentation and/or other materials provided with the distribution. |
  24. // |                                                                      |
  25. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  26. // | Lukas Smith nor the names of his contributors may be used to endorse |
  27. // | or promote products derived from this software without specific prior|
  28. // | written permission.                                                  |
  29. // |                                                                      |
  30. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  31. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  32. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  33. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  34. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  35. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  36. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  37. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  38. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  39. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  40. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  41. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  42. // +----------------------------------------------------------------------+
  43. // | Author: Lukas Smith <smith@backendmedia.com>                         |
  44. // +----------------------------------------------------------------------+
  45. //
  46. // $Id: mysql.php,v 1.13 2004/04/25 10:04:59 lsmith Exp $
  47. //
  48.  
  49. /**
  50.  * MDB2 MySQL driver
  51.  *
  52.  * @package MDB2
  53.  * @category Database
  54.  * @author  Lukas Smith <smith@backendmedia.com>
  55.  */
  56. {
  57.     // {{{ properties
  58.     var $escape_quotes = "\\";
  59.  
  60.     var $dummy_primary_key = 'dummy_primary_key';
  61.  
  62.     // }}}
  63.     // {{{ constructor
  64.  
  65.     /**
  66.     * Constructor
  67.     */
  68.     function MDB2_Driver_mysql()
  69.     {
  70.         $this->MDB2_Driver_Common();
  71.         $this->phptype 'mysql';
  72.         $this->dbsyntax 'mysql';
  73.  
  74.         $this->supported['sequences'= true;
  75.         $this->supported['indexes'= true;
  76.         $this->supported['affected_rows'= true;
  77.         $this->supported['summary_functions'= true;
  78.         $this->supported['order_by_text'= true;
  79.         $this->supported['current_id'= true;
  80.         $this->supported['limit_queries'= true;
  81.         $this->supported['LOBs'= true;
  82.         $this->supported['replace'= true;
  83.         $this->supported['sub_selects'= false;
  84.  
  85.         $this->options['default_table_type'= false;
  86.     }
  87.  
  88.     // }}}
  89.     // {{{ errorInfo()
  90.  
  91.     /**
  92.      * This method is used to collect information about an error
  93.      *
  94.      * @param integer $error 
  95.      * @return array 
  96.      * @access public
  97.      */
  98.     function errorInfo($error = null)
  99.     {
  100.         $native_code @mysql_errno($this->connection);
  101.         $native_msg  @mysql_error($this->connection);
  102.         if (is_null($error)) {
  103.             static $ecode_map;
  104.             if (empty($ecode_map)) {
  105.                 $ecode_map = array(
  106.                     1004 => MDB2_ERROR_CANNOT_CREATE,
  107.                     1005 => MDB2_ERROR_CANNOT_CREATE,
  108.                     1006 => MDB2_ERROR_CANNOT_CREATE,
  109.                     1007 => MDB2_ERROR_ALREADY_EXISTS,
  110.                     1008 => MDB2_ERROR_CANNOT_DROP,
  111.                     1022 => MDB2_ERROR_ALREADY_EXISTS,
  112.                     1046 => MDB2_ERROR_NODBSELECTED,
  113.                     1050 => MDB2_ERROR_ALREADY_EXISTS,
  114.                     1051 => MDB2_ERROR_NOSUCHTABLE,
  115.                     1054 => MDB2_ERROR_NOSUCHFIELD,
  116.                     1062 => MDB2_ERROR_ALREADY_EXISTS,
  117.                     1064 => MDB2_ERROR_SYNTAX,
  118.                     1100 => MDB2_ERROR_NOT_LOCKED,
  119.                     1136 => MDB2_ERROR_VALUE_COUNT_ON_ROW,
  120.                     1146 => MDB2_ERROR_NOSUCHTABLE,
  121.                     1048 => MDB2_ERROR_CONSTRAINT,
  122.                     1213 => MDB2_ERROR_DEADLOCK,
  123.                     1216 => MDB2_ERROR_CONSTRAINT,
  124.                 );
  125.             }
  126.             if (isset($ecode_map[$native_code])) {
  127.                 $error $ecode_map[$native_code];
  128.             else if ($this->options['portability'MDB2_PORTABILITY_ERRORS{
  129.                 if ($native_code == 1022$error MDB2_ERROR_CONSTRAINT;
  130.                 if ($native_code == 1048$error MDB2_ERROR_CONSTRAINT_NOT_NULL;
  131.                 if ($native_code == 1062$error MDB2_ERROR_CONSTRAINT;
  132.             }
  133.         }
  134.         return array($error$native_code$native_msg);
  135.     }
  136.  
  137.     // }}}
  138.     // {{{ escape()
  139.  
  140.     /**
  141.      * Quotes a string so it can be safely used in a query. It will quote
  142.      * the text so it can safely be used within a query.
  143.      *
  144.      * @param string $text the input string to quote
  145.      * @return string quoted string
  146.      * @access public
  147.      */
  148.     function escape($text)
  149.     {
  150.         return @mysql_escape_string($text);
  151.     }
  152.  
  153.     // }}}
  154.     // {{{ quoteIdentifier()
  155.  
  156.     /**
  157.      * Quote a string so it can be safely used as a table or column name
  158.      *
  159.      * Quoting style depends on which database driver is being used.
  160.      *
  161.      * MySQL can't handle the backtick character (<kbd>`</kbd>) in
  162.      * table or column names.
  163.      *
  164.      * @param string $str  identifier name to be quoted
  165.      *
  166.      * @return string  quoted identifier string
  167.      *
  168.      * @access public
  169.      * @internal
  170.      */
  171.     function quoteIdentifier($str)
  172.     {
  173.         return '`' $str '`';
  174.     }
  175.  
  176.     // }}}
  177.     // {{{ autoCommit()
  178.  
  179.     /**
  180.      * Define whether database changes done on the database be automatically
  181.      * committed. This function may also implicitly start or end a transaction.
  182.      *
  183.      * @param boolean $auto_commit    flag that indicates whether the database
  184.      *                                 changes should be committed right after
  185.      *                                 executing every query statement. If this
  186.      *                                 argument is 0 a transaction implicitly
  187.      *                                 started. Otherwise, if a transaction is
  188.      *                                 in progress it is ended by committing any
  189.      *                                 database changes that were pending.
  190.      *
  191.      * @access public
  192.      *
  193.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  194.      */
  195.     function autoCommit($auto_commit)
  196.     {
  197.         $this->debug(($auto_commit 'On' 'Off')'autoCommit');
  198.         if (!isset($this->supported['transactions'])) {
  199.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  200.                 'autoCommit: transactions are not in use');
  201.         }
  202.         if ($this->auto_commit == $auto_commit{
  203.             return MDB2_OK;
  204.         }
  205.         if ($this->connection{
  206.             if ($auto_commit{
  207.                 $result $this->query('COMMIT');
  208.                 if (MDB2::isError($result)) {
  209.                     return $result;
  210.                 }
  211.                 $result $this->query('SET AUTOCOMMIT = 1');
  212.                 if (MDB2::isError($result)) {
  213.                     return $result;
  214.                 }
  215.             else {
  216.                 $result $this->query('SET AUTOCOMMIT = 0');
  217.                 if (MDB2::isError($result)) {
  218.                     return $result;
  219.                 }
  220.             }
  221.         }
  222.         $this->auto_commit = $auto_commit;
  223.         $this->in_transaction !$auto_commit;
  224.         return MDB2_OK;
  225.     }
  226.  
  227.     // }}}
  228.     // {{{ commit()
  229.  
  230.     /**
  231.      * Commit the database changes done during a transaction that is in
  232.      * progress. This function may only be called when auto-committing is
  233.      * disabled, otherwise it will fail. Therefore, a new transaction is
  234.      * implicitly started after committing the pending changes.
  235.      *
  236.      * @access public
  237.      *
  238.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  239.      */
  240.     function commit()
  241.     {
  242.         $this->debug('commit transaction''commit');
  243.         if (!isset($this->supported['transactions'])) {
  244.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  245.                 'commit: transactions are not in use');
  246.         }
  247.         if ($this->auto_commit{
  248.             return $this->raiseError(MDB2_ERRORnullnull,
  249.             'commit: transaction changes are being auto commited');
  250.         }
  251.         return $this->query('COMMIT');
  252.     }
  253.  
  254.     // }}}
  255.     // {{{ rollback()
  256.  
  257.     /**
  258.      * Cancel any database changes done during a transaction that is in
  259.      * progress. This function may only be called when auto-committing is
  260.      * disabled, otherwise it will fail. Therefore, a new transaction is
  261.      * implicitly started after canceling the pending changes.
  262.      *
  263.      * @access public
  264.      *
  265.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  266.      */
  267.     function rollback()
  268.     {
  269.         $this->debug('rolling back transaction''rollback');
  270.         if (!isset($this->supported['transactions'])) {
  271.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  272.                 'rollback: transactions are not in use');
  273.         }
  274.         if ($this->auto_commit{
  275.             return $this->raiseError(MDB2_ERRORnullnull,
  276.                 'rollback: transactions can not be rolled back when changes are auto commited');
  277.         }
  278.         return $this->query('ROLLBACK');
  279.     }
  280.  
  281.     // }}}
  282.     // {{{ connect()
  283.  
  284.     /**
  285.      * Connect to the database
  286.      *
  287.      * @return true on success, MDB2 Error Object on failure
  288.      ***/
  289.     function connect()
  290.     {
  291.         if ($this->connection != 0{
  292.             if (count(array_diff($this->connected_dsn$this->dsn)) == 0
  293.                 && $this->opened_persistent == $this->options['persistent']
  294.             {
  295.                 return MDB2_OK;
  296.             }
  297.             @mysql_close($this->connection);
  298.             $this->connection = 0;
  299.         }
  300.  
  301.         if (!PEAR::loadExtension($this->phptype)) {
  302.             return $this->raiseError(MDB2_ERROR_NOT_FOUNDnullnull,
  303.                 'connect: extension '.$this->phptype.' is not compiled into PHP');
  304.         }
  305.  
  306.         $function ($this->options['persistent''mysql_pconnect' 'mysql_connect');
  307.  
  308.         $dsninfo $this->dsn;
  309.         if (isset($dsninfo['protocol']&& $dsninfo['protocol'== 'unix'{
  310.             $dbhost ':' $dsninfo['socket'];
  311.         else {
  312.             $dbhost $dsninfo['hostspec'$dsninfo['hostspec''localhost';
  313.             if (!empty($dsninfo['port'])) {
  314.                 $dbhost .= ':' $dsninfo['port'];
  315.             }
  316.         }
  317.         $user $dsninfo['username'];
  318.         $pw $dsninfo['password'];
  319.  
  320.         @ini_set('track_errors'true);
  321.         $connection @$function($dbhost$user$pwtrue);
  322.         @ini_restore('track_errors');
  323.         if ($connection <= 0{
  324.             return $this->raiseError(MDB2_ERROR_CONNECT_FAILEDnullnull,
  325.                 $php_errormsg);
  326.         }
  327.         $this->connection $connection;
  328.         $this->connected_dsn $this->dsn;
  329.         $this->connected_database_name '';
  330.         $this->opened_persistent $this->options['persistent'];
  331.  
  332.         if ($this->options['use_transactions']{
  333.             $this->supported['transactions'= true;
  334.             $this->options['default_table_type''BDB';
  335.         else {
  336.             $this->options['default_table_type''';
  337.         }
  338.  
  339.         $default_table_type $this->options['default_table_type'];
  340.         if ($default_table_type{
  341.             switch ($this->options['default_table_type'strtoupper($default_table_type)) {
  342.                 case 'BERKELEYDB':
  343.                     $this->options['default_table_type''BDB';
  344.                 case 'BDB':
  345.                 case 'INNODB':
  346.                 case 'GEMINI':
  347.                     break;
  348.                 case 'HEAP':
  349.                 case 'ISAM':
  350.                 case 'MERGE':
  351.                 case 'MRG_MYISAM':
  352.                 case 'MYISAM':
  353.                     if (isset($this->supported['transactions'])) {
  354.                         $this->warnings[$default_table_type.
  355.                             ' is not a transaction-safe default table type';
  356.                     }
  357.                     break;
  358.                 default:
  359.                     $this->warnings[$default_table_type.
  360.                         ' is not a supported default table type';
  361.             }
  362.         }
  363.  
  364.         if (isset($this->supported['transactions']&& !$this->auto_commit{
  365.             if (!@mysql_query('SET AUTOCOMMIT = 0'$this->connection)) {
  366.                 @mysql_close($this->connection);
  367.                 $this->connection = 0;
  368.                 return $this->raiseError();
  369.             }
  370.             $this->in_transaction = true;
  371.         }
  372.         return MDB2_OK;
  373.     }
  374.  
  375.     // }}}
  376.     // {{{ _close()
  377.     /**
  378.      * all the RDBMS specific things needed close a DB connection
  379.      *
  380.      * @return boolean 
  381.      * @access private
  382.      ***/
  383.     function _close()
  384.     {
  385.         if ($this->connection != 0{
  386.             if (isset($this->supported['transactions']&& !$this->auto_commit{
  387.                 $result $this->autoCommit(true);
  388.             }
  389.             @mysql_close($this->connection);
  390.             $this->connection = 0;
  391.             unset($GLOBALS['_MDB2_databases'][$this->db_index]);
  392.  
  393.             if (isset($result&& MDB2::isError($result)) {
  394.                 return $result;
  395.             }
  396.         }
  397.         return MDB2_OK;
  398.     }
  399.  
  400.     // }}}
  401.     // {{{ _modifyQuery()
  402.  
  403.     /**
  404.      * This method is used by backends to alter queries for various
  405.      * reasons.
  406.      *
  407.      * @param string $query  query to modify
  408.      * @return the new (modified) query
  409.      * @access private
  410.      */
  411.     function _modifyQuery($query)
  412.     {
  413.         // "DELETE FROM table" gives 0 affected rows in mysql.
  414.         // This little hack lets you know how many rows were deleted.
  415.         if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i'$query)) {
  416.             $query preg_replace(
  417.                 '/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
  418.                 'DELETE FROM \1 WHERE 1=1'$query
  419.             );
  420.         }
  421.         return $query;
  422.     }
  423.  
  424.     // }}}
  425.     // {{{ query()
  426.  
  427.     /**
  428.      * Send a query to the database and return any results
  429.      *
  430.      * @param string  $query  the SQL query
  431.      * @param mixed   $types  string or array that contains the types of the
  432.      *                         columns in the result set
  433.      * @param mixed $result_class string which specifies which result class to use
  434.      * @param mixed $result_wrap_class string which specifies which class to wrap results in
  435.      * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
  436.      *
  437.      * @access public
  438.      */
  439.     function &query($query$types = null$result_class = false$result_wrap_class = false)
  440.     {
  441.         $ismanip MDB2::isManip($query);
  442.         $offset $this->row_offset;
  443.         $limit $this->row_limit;
  444.         $this->row_offset $this->row_limit = 0;
  445.         if ($limit > 0{
  446.             if ($ismanip{
  447.                 $query .= " LIMIT $limit";
  448.             else {
  449.                 $query .= " LIMIT $offset,$limit";
  450.             }
  451.         }
  452.         if ($this->options['portability'MDB2_PORTABILITY_DELETE_COUNT{
  453.             $query $this->_modifyQuery($query);
  454.         }
  455.         $this->last_query = $query;
  456.         $this->debug($query'query');
  457.  
  458.         $connected $this->connect();
  459.         if (MDB2::isError($connected)) {
  460.             return $connected;
  461.         }
  462.  
  463.         if ($this->database_name
  464.             && $this->database_name != $this->connected_database_name
  465.         {
  466.             if (!@mysql_select_db($this->database_name$this->connection)) {
  467.                 $error =$this->raiseError();
  468.                 return $error;
  469.             }
  470.             $this->connected_database_name $this->database_name;
  471.         }
  472.  
  473.         $function $this->options['result_buffering']
  474.             ? 'mysql_query' 'mysql_unbuffered_query';
  475.         if ($result @$function($query$this->connection)) {
  476.             if ($ismanip{
  477.                 return MDB2_OK;
  478.             else {
  479.                 if (!$result_class{
  480.                     $result_class $this->options['result_buffering']
  481.                         ? $this->options['buffered_result_class'$this->options['result_class'];
  482.                 }
  483.                 $class_name sprintf($result_class$this->phptype);
  484.                 $result =new $class_name($this$result);
  485.                 if ($types{
  486.                     $err $result->setResultTypes($types);
  487.                     if (MDB2::isError($err)) {
  488.                         $result->free();
  489.                         return $err;
  490.                     }
  491.                 }
  492.                 if (!$result_wrap_class{
  493.                     $result_wrap_class $this->options['result_wrap_class'];
  494.                 }
  495.                 if ($result_wrap_class{
  496.                     $result =new $result_wrap_class($result);
  497.                 }
  498.                 return $result;
  499.             }
  500.         }
  501.         $error =$this->raiseError();
  502.         return $error;
  503.     }
  504.  
  505.     // }}}
  506.     // {{{ affectedRows()
  507.  
  508.     /**
  509.      * returns the affected rows of a query
  510.      *
  511.      * @return mixed MDB2 Error Object or number of rows
  512.      * @access public
  513.      */
  514.     function affectedRows()
  515.     {
  516.         $affected_rows @mysql_affected_rows($this->connection);
  517.         if ($affected_rows === false{
  518.             return $this->raiseError(MDB2_ERROR_NEED_MORE_DATA);
  519.         }
  520.         return $affected_rows;
  521.     }
  522.  
  523.     // }}}
  524.     // {{{ subSelect()
  525.  
  526.     /**
  527.      * simple subselect emulation for Mysql
  528.      *
  529.      * @access public
  530.      *
  531.      * @param string $query the SQL query for the subselect that may only
  532.      *                       return a column
  533.      * @param string $type determines type of the field
  534.      *
  535.      * @return string comma seperated values
  536.      */
  537.     function subSelect($query$type = false)
  538.     {
  539.         if ($this->supported['sub_selects'== true{
  540.             return $query;
  541.         }
  542.         $col $this->queryCol($query$type);
  543.         if (!is_array($col|| count($col== 0{
  544.             return 'NULL';
  545.         }
  546.         if ($type{
  547.             $this->loadModule('datatype');
  548.             return $this->datatype->implodeArray($col$type);
  549.         }
  550.         return implode(', '$col);
  551.     }
  552.  
  553.     // }}}
  554.     // {{{ replace()
  555.  
  556.     /**
  557.      * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
  558.      * query, except that if there is already a row in the table with the same
  559.      * key field values, the REPLACE query just updates its values instead of
  560.      * inserting a new row.
  561.      *
  562.      * The REPLACE type of query does not make part of the SQL standards. Since
  563.      * practically only MySQL implements it natively, this type of query is
  564.      * emulated through this method for other DBMS using standard types of
  565.      * queries inside a transaction to assure the atomicity of the operation.
  566.      *
  567.      * @access public
  568.      *
  569.      * @param string $table name of the table on which the REPLACE query will
  570.      *   be executed.
  571.      * @param array $fields associative array that describes the fields and the
  572.      *   values that will be inserted or updated in the specified table. The
  573.      *   indexes of the array are the names of all the fields of the table. The
  574.      *   values of the array are also associative arrays that describe the
  575.      *   values and other properties of the table fields.
  576.      *
  577.      *   Here follows a list of field properties that need to be specified:
  578.      *
  579.      *     value:
  580.      *           Value to be assigned to the specified field. This value may be
  581.      *           of specified in database independent type format as this
  582.      *           function can perform the necessary datatype conversions.
  583.      *
  584.      *     Default:
  585.      *           this property is required unless the Null property
  586.      *           is set to 1.
  587.      *
  588.      *     type
  589.      *           Name of the type of the field. Currently, all types Metabase
  590.      *           are supported except for clob and blob.
  591.      *
  592.      *     Default: no type conversion
  593.      *
  594.      *     null
  595.      *           Boolean property that indicates that the value for this field
  596.      *           should be set to null.
  597.      *
  598.      *           The default value for fields missing in INSERT queries may be
  599.      *           specified the definition of a table. Often, the default value
  600.      *           is already null, but since the REPLACE may be emulated using
  601.      *           an UPDATE query, make sure that all fields of the table are
  602.      *           listed in this function argument array.
  603.      *
  604.      *     Default: 0
  605.      *
  606.      *     key
  607.      *           Boolean property that indicates that this field should be
  608.      *           handled as a primary key or at least as part of the compound
  609.      *           unique index of the table that will determine the row that will
  610.      *           updated if it exists or inserted a new row otherwise.
  611.      *
  612.      *           This function will fail if no key field is specified or if the
  613.      *           value of a key field is set to null because fields that are
  614.      *           part of unique index they may not be null.
  615.      *
  616.      *     Default: 0
  617.      *
  618.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  619.      */
  620.     function replace($table$fields)
  621.     {
  622.         $count count($fields);
  623.         for ($keys = 0$query $values '',reset($fields)$colnum = 0;
  624.             $colnum $count;
  625.             next($fields)$colnum++)
  626.         {
  627.             $name key($fields);
  628.             if ($colnum > 0{
  629.                 $query .= ',';
  630.                 $values .= ',';
  631.             }
  632.             $query .= $name;
  633.             if (isset($fields[$name]['null']&& $fields[$name]['null']{
  634.                 $value 'NULL';
  635.             else {
  636.                 $value $this->quote($fields[$name]['value']$fields[$name]['type']);
  637.             }
  638.             $values .= $value;
  639.             if (isset($fields[$name]['key']&& $fields[$name]['key']{
  640.                 if ($value === 'NULL'{
  641.                     return $this->raiseError(MDB2_ERROR_CANNOT_REPLACEnullnull,
  642.                         'replace: key value '.$name.' may not be NULL');
  643.                 }
  644.                 $keys++;
  645.             }
  646.         }
  647.         if ($keys == 0{
  648.             return $this->raiseError(MDB2_ERROR_CANNOT_REPLACEnullnull,
  649.                 'replace: not specified which fields are keys');
  650.         }
  651.         return $this->query("REPLACE INTO $table ($query) VALUES ($values)");
  652.     }
  653.  
  654.     // }}}
  655.     // {{{ nextID()
  656.  
  657.     /**
  658.      * returns the next free id of a sequence
  659.      *
  660.      * @param string  $seq_name name of the sequence
  661.      * @param boolean $ondemand when true the seqence is
  662.      *                           automatic created, if it
  663.      *                           not exists
  664.      *
  665.      * @return mixed MDB2 Error Object or id
  666.      * @access public
  667.      */
  668.     function nextID($seq_name$ondemand = true)
  669.     {
  670.         $sequence_name $this->getSequenceName($seq_name);
  671.         $this->expectError(MDB2_ERROR_NOSUCHTABLE);
  672.         $result =$this->query("INSERT INTO $sequence_name VALUES (NULL)");
  673.         $this->popExpect();
  674.         if (MDB2::isError($result)) {
  675.             if ($ondemand && $result->getCode(== MDB2_ERROR_NOSUCHTABLE{
  676.                 $this->loadModule('manager');
  677.                 // Since we are creating the sequence on demand
  678.                 // we know the first id = 1 so initialize the
  679.                 // sequence at 2
  680.                 $result $this->manager->createSequence($seq_name2);
  681.                 if (MDB2::isError($result)) {
  682.                     return $this->raiseError(MDB2_ERRORnullnull,
  683.                         'nextID: on demand sequence '.$seq_name.' could not be created');
  684.                 else {
  685.                     // First ID of a newly created sequence is 1
  686.                     return 1;
  687.                 }
  688.             }
  689.             return $result;
  690.         }
  691.         $value $this->queryOne('SELECT LAST_INSERT_ID()''integer');
  692.         if (is_numeric($value)
  693.             && MDB2::isError($this->query("DELETE FROM $sequence_name WHERE ".$this->options['seqname_col_name']." < $value"))
  694.         {
  695.             $this->warnings['nextID: could not delete previous sequence table values from '.$seq_name;
  696.         }
  697.         return $value;
  698.     }
  699.  
  700.     // }}}
  701.     // {{{ currID()
  702.  
  703.     /**
  704.      * returns the current id of a sequence
  705.      *
  706.      * @param string  $seq_name name of the sequence
  707.      * @return mixed MDB2 Error Object or id
  708.      * @access public
  709.      */
  710.     function currID($seq_name)
  711.     {
  712.         $sequence_name $this->getSequenceName($seq_name);
  713.         return $this->queryOne("SELECT MAX(".$this->options['seqname_col_name'].") FROM $sequence_name"'integer');
  714.     }
  715. }
  716.  
  717. class MDB2_Result_mysql extends MDB2_Result_Common
  718. {
  719.     // }}}
  720.     // {{{ constructor
  721.  
  722.     /**
  723.      * Constructor
  724.      */
  725.     function MDB2_Result_mysql(&$mdb&$result)
  726.     {
  727.         parent::MDB2_Result_Common($mdb$result);
  728.     }
  729.  
  730.     // }}}
  731.     // {{{ fetch()
  732.  
  733.     /**
  734.     * fetch value from a result set
  735.     *
  736.     * @param int    $rownum    number of the row where the data can be found
  737.     * @param int    $colnum    field number where the data can be found
  738.     * @return mixed string on success, a MDB2 error on failure
  739.     * @access public
  740.     */
  741.     function fetch($rownum = 0$colnum = 0)
  742.     {
  743.         $value @mysql_result($this->result$rownum$colnum);
  744.         if (!$value{
  745.             if (is_null($this->result)) {
  746.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  747.                     'fetch: resultset has already been freed');
  748.             }
  749.         }
  750.         if (isset($this->types[$colnum])) {
  751.             $value $this->mdb->datatype->convertResult($value$this->types[$colnum]);
  752.         }
  753.         if ($this->mdb->options['portability'MDB2_PORTABILITY_RTRIM{
  754.             $value rtrim($value);
  755.         }
  756.         if ($value === ''
  757.             && $this->mdb->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL
  758.         {
  759.             $value = null;
  760.         }
  761.         return $value;
  762.     }
  763.  
  764.     // }}}
  765.     // {{{ fetchRow()
  766.  
  767.     /**
  768.      * Fetch a row and insert the data into an existing array.
  769.      *
  770.      * @param int       $fetchmode  how the array data should be indexed
  771.      * @return int data array on success, a MDB2 error on failure
  772.      * @access public
  773.      */
  774.     function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT)
  775.     {
  776.         if ($fetchmode == MDB2_FETCHMODE_DEFAULT{
  777.             $fetchmode $this->mdb->fetchmode;
  778.         }
  779.         if ($fetchmode MDB2_FETCHMODE_ASSOC{
  780.             $row @mysql_fetch_assoc($this->result);
  781.             if (is_array($row)
  782.                 && $this->mdb->options['portability'MDB2_PORTABILITY_LOWERCASE
  783.             {
  784.                 $row array_change_key_case($rowCASE_LOWER);
  785.             }
  786.         else {
  787.            $row @mysql_fetch_row($this->result);
  788.         }
  789.         if (!$row{
  790.             if (is_null($this->result)) {
  791.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  792.                     'fetchRow: resultset has already been freed');
  793.             }
  794.             return null;
  795.         }
  796.         if (isset($this->types)) {
  797.             $row $this->mdb->datatype->convertResultRow($this->types$row);
  798.         }
  799.         if ($this->mdb->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL{
  800.             $this->mdb->_convertEmptyArrayValuesToNull($row);
  801.         }
  802.         ++$this->rownum;
  803.         return $row;
  804.     }
  805.  
  806.     // }}}
  807.     // {{{ getColumnNames()
  808.  
  809.     /**
  810.      * Retrieve the names of columns returned by the DBMS in a query result.
  811.      *
  812.      * @return mixed                an associative array variable
  813.      *                               that will hold the names of columns. The
  814.      *                               indexes of the array are the column names
  815.      *                               mapped to lower case and the values are the
  816.      *                               respective numbers of the columns starting
  817.      *                               from 0. Some DBMS may not return any
  818.      *                               columns when the result set does not
  819.      *                               contain any rows.
  820.      *
  821.      *                               a MDB2 error on failure
  822.      * @access public
  823.      */
  824.     function getColumnNames()
  825.     {
  826.         $columns = array();
  827.         $numcols $this->numCols();
  828.         if (MDB2::isError($numcols)) {
  829.             return $numcols;
  830.         }
  831.         for ($column = 0; $column $numcols$column++{
  832.             $column_name @mysql_field_name($this->result$column);
  833.             $columns[$column_name$column;
  834.         }
  835.         if ($this->mdb->options['portability'MDB2_PORTABILITY_LOWERCASE{
  836.             $columns array_change_key_case($columnsCASE_LOWER);
  837.         }
  838.         return $columns;
  839.     }
  840.  
  841.     // }}}
  842.     // {{{ numCols()
  843.  
  844.     /**
  845.      * Count the number of columns returned by the DBMS in a query result.
  846.      *
  847.      * @access public
  848.      * @return mixed integer value with the number of columns, a MDB2 error
  849.      *                        on failure
  850.      */
  851.     function numCols()
  852.     {
  853.         $cols @mysql_num_fields($this->result);
  854.         if (is_null($cols)) {
  855.             if (is_null($this->result)) {
  856.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  857.                     'numCols: resultset has already been freed');
  858.             }
  859.             return $this->mdb->raiseError();
  860.         }
  861.         return $cols;
  862.     }
  863.  
  864.     // }}}
  865.     // {{{ free()
  866.  
  867.     /**
  868.      * Free the internal resources associated with result.
  869.      *
  870.      * @return boolean true on success, false if result is invalid
  871.      * @access public
  872.      */
  873.     function free()
  874.     {
  875.         $free @mysql_free_result($this->result);
  876.         if (!$free{
  877.             if (is_null($this->result)) {
  878.                 return MDB2_OK;
  879.             }
  880.             return $this->mdb->raiseError();
  881.         }
  882.         $this->result = null;
  883.         return MDB2_OK;
  884.     }
  885. }
  886.  
  887. class MDB2_BufferedResult_mysql extends MDB2_Result_mysql
  888. {
  889.     // }}}
  890.     // {{{ constructor
  891.  
  892.     /**
  893.      * Constructor
  894.      */
  895.     function MDB2_BufferedResult_mysql(&$mdb&$result)
  896.     {
  897.         parent::MDB2_Result_mysql($mdb$result);
  898.     }
  899.  
  900.     // }}}
  901.     // {{{ seek()
  902.  
  903.     /**
  904.     * seek to a specific row in a result set
  905.     *
  906.     * @param int    $rownum    number of the row where the data can be found
  907.     * @return mixed MDB2_OK on success, a MDB2 error on failure
  908.     * @access public
  909.     */
  910.     function seek($rownum = 0)
  911.     {
  912.         if (!@mysql_data_seek($this->result$rownum)) {
  913.             if (is_null($this->result)) {
  914.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  915.                     'seek: resultset has already been freed');
  916.             }
  917.             return $this->mdb->raiseError(MDB2_ERROR_INVALIDnullnull,
  918.                 'seek: tried to seek to an invalid row number ('.$rownum.')');
  919.         }
  920.         $this->rownum $rownum - 1;
  921.         return MDB2_OK;
  922.     }
  923.  
  924.     // }}}
  925.     // {{{ valid()
  926.  
  927.     /**
  928.     * check if the end of the result set has been reached
  929.     *
  930.     * @return mixed true or false on sucess, a MDB2 error on failure
  931.     * @access public
  932.     */
  933.     function valid()
  934.     {
  935.         $numrows $this->numRows();
  936.         if (MDB2::isError($numrows)) {
  937.             return $numrows;
  938.         }
  939.         return $this->rownum ($numrows - 1);
  940.     }
  941.  
  942.     // }}}
  943.     // {{{ numRows()
  944.  
  945.     /**
  946.     * returns the number of rows in a result object
  947.     *
  948.     * @return mixed MDB2 Error Object or the number of rows
  949.     * @access public
  950.     */
  951.     function numRows()
  952.     {
  953.         $rows @mysql_num_rows($this->result);
  954.         if (is_null($rows)) {
  955.             if (is_null($this->result)) {
  956.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  957.                     'numRows: resultset has already been freed');
  958.             }
  959.             return $this->raiseError();
  960.         }
  961.         return $rows;
  962.     }
  963. }
  964.  
  965. ?>

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