home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / DB / Table / Base.php next >
Encoding:
PHP Script  |  2008-07-02  |  26.2 KB  |  756 lines

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  4.  
  5. /**
  6.  * DB_Table_Base Base class for DB_Table and DB_Table_Database
  7.  *
  8.  * This utility class contains properties and methods that are common
  9.  * to DB_Table and DB_Table database. These are all related to one of:
  10.  *   - DB/MDB2 connection object [ $db and $backend properties ]
  11.  *   - Error handling [ throwError() method, $error and $_primary_subclass ]
  12.  *   - SELECT queries [ select*() methods, $sql & $fetchmode* properties]
  13.  *   - buildSQL() and quote() SQL utilities
  14.  *   - _swapModes() method 
  15.  * 
  16.  * PHP versions 4 and 5
  17.  *
  18.  * LICENSE:
  19.  * 
  20.  * Copyright (c) 1997-2007, Paul M. Jones <pmjones@php.net>
  21.  *                          David C. Morse <morse@php.net>
  22.  *                          Mark Wiesemann <wiesemann@php.net>
  23.  * All rights reserved.
  24.  *
  25.  * Redistribution and use in source and binary forms, with or without
  26.  * modification, are permitted provided that the following conditions
  27.  * are met:
  28.  *
  29.  *    * Redistributions of source code must retain the above copyright
  30.  *      notice, this list of conditions and the following disclaimer.
  31.  *    * Redistributions in binary form must reproduce the above copyright
  32.  *      notice, this list of conditions and the following disclaimer in the 
  33.  *      documentation and/or other materials provided with the distribution.
  34.  *    * The names of the authors may not be used to endorse or promote products 
  35.  *      derived from this software without specific prior written permission.
  36.  *
  37.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  38.  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  39.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  40.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  41.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  42.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  43.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  44.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  45.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  46.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  47.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  48.  *
  49.  * @category Database
  50.  * @package  DB_Table
  51.  * @author   Paul M. Jones <pmjones@php.net>
  52.  * @author   David C. Morse <morse@php.net>
  53.  * @author   Mark Wiesemann <wiesemann@php.net>
  54.  * @license  http://opensource.org/licenses/bsd-license.php New BSD License
  55.  * @version  CVS: $Id: Base.php,v 1.4 2007/12/13 16:52:14 wiesemann Exp $
  56.  * @link     http://pear.php.net/package/DB_Table
  57.  */
  58.  
  59. require_once 'PEAR.php';
  60.  
  61. // {{{ DB_Table_Base
  62.  
  63. /**
  64.  * Base class for DB_Table and DB_Table_Database
  65.  *
  66.  * @category Database
  67.  * @package  DB_Table
  68.  * @author   Paul M. Jones <pmjones@php.net>
  69.  * @author   David C. Morse <morse@php.net>
  70.  * @author   Mark Wiesemann <wiesemann@php.net>
  71.  * @version  Release: 1.5.5
  72.  * @link     http://pear.php.net/package/DB_Table
  73.  */
  74. class DB_Table_Base
  75. {
  76.  
  77.     // {{{ properties
  78.  
  79.     /**
  80.      * The PEAR DB/MDB2 object that connects to the database.
  81.      *
  82.      * @var    object
  83.      * @access public
  84.      */
  85.     var $db = null;
  86.  
  87.     /**
  88.      * The backend type, which must be 'db' or 'mdb2'
  89.      *
  90.      * @var    string
  91.      * @access public
  92.      */
  93.     var $backend = null;
  94.  
  95.     /**
  96.     * If there is an error on instantiation, this captures that error.
  97.     *
  98.     * This property is used only for errors encountered in the constructor
  99.     * at instantiation time.  To check if there was an instantiation error...
  100.     *
  101.     * <code>
  102.     * $obj =& new DB_Table_*();
  103.     * if ($obj->error) {
  104.     *     // ... error handling code here ...
  105.     * }
  106.     * </code>
  107.     *
  108.     * @var    object PEAR_Error
  109.     * @access public
  110.     */
  111.     var $error = null;
  112.  
  113.     /**
  114.      * Baseline SELECT maps for buildSQL() and select*() methods.
  115.      *
  116.      * @var    array
  117.      * @access public
  118.      */
  119.     var $sql = array();
  120.  
  121.     /**
  122.      * Format of rows in sets returned by the select() method 
  123.      *
  124.      * This should be one of the DB/MDB2_FETCHMODE_* constant values, such as
  125.      * MDB2_FETCHMODE_ASSOC, MDB2_FETCHMODE_ORDERED, or MDB2_FETCHMODE_OBJECT.
  126.      * It determines whether select() returns represents individual rows as
  127.      * associative arrays with column name keys, ordered/sequential arrays, 
  128.      * or objects with column names mapped to properties. Use corresponding
  129.      * DB_FETCHMODE_* constants for use with the DB backend. It has no effect
  130.      * upon the return value of selectResult().
  131.      *
  132.      * If a 'fetchmode' element is set for a specific query array, the query 
  133.      * fetchmode will override this DB_Table or DB_Table_Database property.
  134.      * If no value is set for the query or the DB_Table_Base object, the value
  135.      * or default set in the underlying DB/MDB2 object will be used.
  136.      *
  137.      * @var    int
  138.      * @access public
  139.      */
  140.     var $fetchmode = null;
  141.  
  142.     /**
  143.      * Class of objects to use for rows returned as objects by select()
  144.      *
  145.      * When fetchmode is DB/MDB2_FETCHMODE_OBJECT, use this class for each
  146.      * returned row in rsults of select(). May be overridden by value of 
  147.      * 'fetchmode_object_class'. If no class name is set in the query or 
  148.      * the DB_Table_Base, defaults to that set in the DB/MDB2 object, or
  149.      * to default of StdObject.
  150.      *
  151.      * @var    string
  152.      * @access public
  153.      */
  154.     var $fetchmode_object_class = null;
  155.  
  156.     /**
  157.      * Upper case name of primary subclass, 'DB_TABLE' or 'DB_TABLE_DATABASE'
  158.      *
  159.      * This should be set in the constructor of the child class, and is 
  160.      * used in the DB_Table_Base::throwError() method to determine the
  161.      * location of the relevant error codes and messages. Error codes and
  162.      * error code messages are defined in class $this->_primary_subclass.
  163.      * Messages are stored in $GLOBALS['_' . $this->_primary_subclass]['error']
  164.      *
  165.      * @var    string
  166.      * @access private
  167.      */
  168.      var $_primary_subclass = null;
  169.  
  170.     // }}}
  171.     // {{{ Methods
  172.  
  173.     /**
  174.      * Specialized version of throwError() modeled on PEAR_Error.
  175.      * 
  176.      * Throws a PEAR_Error with an error message based on an error code 
  177.      * and corresponding error message defined in $this->_primary_subclass
  178.      * 
  179.      * @param string $code  An error code constant 
  180.      * @param string $extra Extra text for the error (in addition to the 
  181.      *                      regular error message).
  182.      * @return object PEAR_Error
  183.      * @access public
  184.      * @static
  185.      */
  186.     function &throwError($code, $extra = null)
  187.     {
  188.         // get the error message text based on the error code
  189.         $index = '_' . $this->_primary_subclass;
  190.         $text = $this->_primary_subclass . " Error - \n" 
  191.               . $GLOBALS[$index]['error'][$code];
  192.         
  193.         // add any additional error text
  194.         if ($extra) {
  195.             $text .= ' ' . $extra;
  196.         }
  197.         
  198.         // done!
  199.         $error = PEAR::throwError($text, $code);
  200.         return $error;
  201.     }
  202.    
  203.     /**
  204.      * Overwrites one or more error messages, e.g., to internationalize them.
  205.      * 
  206.      * May be used to change messages stored in global array $GLOBALS[$class_key]
  207.      * @param mixed $code If string, the error message with code $code will be
  208.      *                    overwritten by $message. If array, each key is a code
  209.      *                    and each value is a new message. 
  210.      * 
  211.      * @param string $message Only used if $key is not an array.
  212.      * @return void
  213.      * @access public
  214.      */
  215.     function setErrorMessage($code, $message = null) {
  216.         $index = '_' . $this->_primary_subclass;
  217.         if (is_array($code)) {
  218.             foreach ($code as $single_code => $single_message) {
  219.                 $GLOBALS[$index]['error'][$single_code] = $single_message;
  220.             }
  221.         } else {
  222.             $GLOBALS[$index]['error'][$code] = $message;
  223.         }
  224.     }
  225.  
  226.  
  227.     /**
  228.      * Returns SQL SELECT string constructed from sql query array
  229.      *
  230.      * @param mixed  $query  SELECT query array, or key string of $this->sql
  231.      * @param string $filter SQL snippet to AND with default WHERE clause
  232.      * @param string $order  SQL snippet to override default ORDER BY clause
  233.      * @param int    $start  The row number from which to start result set
  234.      * @param int    $count  The number of rows to list in the result set.
  235.      *
  236.      * @return string SQL SELECT command string (or PEAR_Error on failure)
  237.      *
  238.      * @access public
  239.      */
  240.     function buildSQL($query, $filter = null, $order = null, 
  241.                               $start = null, $count = null)
  242.     {
  243.  
  244.         // Is $query a query array or a key of $this->sql ?
  245.         if (!is_array($query)) {
  246.             if (is_string($query)) {
  247.                 if (isset($this->sql[$query])) {
  248.                     $query = $this->sql[$query];
  249.                 } else {
  250.                     return $this->throwError(
  251.                            constant($this->_primary_subclass . '_ERR_SQL_UNDEF'),
  252.                            $query);
  253.                 }
  254.             } else {
  255.                 return $this->throwError(
  256.                        constant($this->_primary_subclass . '_ERR_SQL_NOT_STRING'));
  257.             }
  258.         }
  259.        
  260.         // Construct SQL command from parts
  261.         $s = array();
  262.         if (isset($query['select'])) {
  263.             $s[] = 'SELECT ' . $query['select'];
  264.         } else {
  265.             $s[] = 'SELECT *';
  266.         }
  267.         if (isset($query['from'])) {
  268.             $s[] = 'FROM ' . $query['from'];
  269.         } elseif ($this->_primary_subclass == 'DB_TABLE') {
  270.             $s[] = 'FROM ' . $this->table;
  271.         }
  272.         if (isset($query['join'])) {
  273.             $s[] = $query['join'];
  274.         }
  275.         if (isset($query['where'])) {
  276.             if ($filter) {
  277.                 $s[] = 'WHERE ( ' . $query['where'] . ' )';
  278.                 $s[] = '  AND ( '. $filter . ' )';
  279.             } else {
  280.                 $s[] = 'WHERE ' . $query['where'];
  281.             }
  282.         } elseif ($filter) {
  283.             $s[] = 'WHERE ' . $filter;
  284.         }
  285.         if (isset($query['group'])) {
  286.             $s[] = 'GROUP BY ' . $query['group'];
  287.         }
  288.         if (isset($query['having'])) {
  289.             $s[] = 'HAVING '. $query['having'];
  290.         }
  291.         // If $order parameter is set, override 'order' element
  292.         if (!is_null($order)) {
  293.             $s[] = 'ORDER BY '. $order;
  294.         } elseif (isset($query['order'])) {
  295.             $s[] = 'ORDER BY ' . $query['order'];
  296.         }
  297.         $cmd = implode("\n", $s);
  298.         
  299.         // add LIMIT if requested
  300.         if (!is_null($start) && !is_null($count)) {
  301.             $db =& $this->db;
  302.             if ($this->backend == 'mdb2') {
  303.                 $db->setLimit($count, $start);
  304.             } else {
  305.                 $cmd = $db->modifyLimitQuery(
  306.                             $cmd, $start, $count);
  307.             }
  308.         }
  309.  
  310.         // Return command string
  311.         return $cmd;
  312.     }
  313.  
  314.   
  315.     /**
  316.      * Selects rows using one of the DB/MDB2 get*() methods.
  317.      *
  318.      * @param string $query SQL SELECT query array, or a key of the
  319.      *                          $this->sql property array.
  320.      * @param string $filter    SQL snippet to AND with default WHERE clause
  321.      * @param string $order     SQL snippet to override default ORDER BY clause
  322.      * @param int    $start     The row number from which to start result set
  323.      * @param int    $count     The number of rows to list in the result set.
  324.      * @param array  $params    Parameters for placeholder substitutions, if any
  325.      * @return mixed  An array of records from the table if anything but 
  326.      *                ('getOne'), a single value (if 'getOne'), or a PEAR_Error
  327.      * @see DB::getAll()
  328.      * @see MDB2::getAll()
  329.      * @see DB::getAssoc()
  330.      * @see MDB2::getAssoc()
  331.      * @see DB::getCol()
  332.      * @see MDB2::getCol()
  333.      * @see DB::getOne()
  334.      * @see MDB2::getOne()
  335.      * @see DB::getRow()
  336.      * @see MDB2::getRow()
  337.      * @see DB_Table_Base::_swapModes()
  338.      * @access public
  339.      */
  340.     function select($query, $filter = null, $order = null,
  341.                             $start = null, $count = null, $params = array())
  342.     {
  343.  
  344.         // Is $query a query array or a key of $this->sql ?
  345.         // On output from this block, $query is an array
  346.         if (!is_array($query)) {
  347.             if (is_string($query)) {
  348.                 if (isset($this->sql[$query])) {
  349.                     $query = $this->sql[$query];
  350.                 } else {
  351.                     return $this->throwError(
  352.                           constant($this->_primary_subclass . '_ERR_SQL_UNDEF'),
  353.                           $query);
  354.                 }
  355.             } else {
  356.                 return $this->throwError(
  357.                     constant($this->_primary_subclass . '_ERR_SQL_NOT_STRING'));
  358.             }
  359.         }
  360.  
  361.         // build the base command
  362.         $sql = $this->buildSQL($query, $filter, $order, $start, $count);
  363.         if (PEAR::isError($sql)) {
  364.             return $sql;
  365.         }
  366.  
  367.         // set the get*() method name
  368.         if (isset($query['get'])) {
  369.             $method = ucwords(strtolower(trim($query['get'])));
  370.             $method = "get$method";
  371.         } else {
  372.             $method = 'getAll';
  373.         }
  374.  
  375.         // DB_Table assumes you are using a shared PEAR DB/MDB2 object.
  376.         // Record fetchmode settings, to be restored before returning.
  377.         $db =& $this->db;
  378.         $restore_mode = $db->fetchmode;
  379.         if ($this->backend == 'mdb2') {
  380.             $restore_class = $db->getOption('fetch_class');
  381.         } else {
  382.             $restore_class = $db->fetchmode_object_class;
  383.         }
  384.  
  385.         // swap modes
  386.         $fetchmode = $this->fetchmode;
  387.         $fetchmode_object_class = $this->fetchmode_object_class;
  388.         if (isset($query['fetchmode'])) {
  389.             $fetchmode = $query['fetchmode'];
  390.         }
  391.         if (isset($query['fetchmode_object_class'])) {
  392.             $fetchmode_object_class = $query['fetchmode_object_class'];
  393.         }
  394.         $this->_swapModes($fetchmode, $fetchmode_object_class);
  395.  
  396.         // make sure params is an array
  397.         if (!is_null($params)) {
  398.             $params = (array) $params;
  399.         }
  400.  
  401.         // get the result
  402.         if ($this->backend == 'mdb2') {
  403.             $result = $db->extended->$method($sql, null, $params);
  404.         } else {
  405.             switch ($method) {
  406.  
  407.                 case 'getCol':
  408.                     $result = $db->$method($sql, 0, $params);
  409.                     break;
  410.  
  411.                 case 'getAssoc':
  412.                     $result = $db->$method($sql, false, $params);
  413.                     break;
  414.  
  415.                 default:
  416.                     $result = $db->$method($sql, $params);
  417.                     break;
  418.  
  419.             }
  420.         }
  421.  
  422.         // restore old fetch_mode and fetch_object_class back
  423.         $this->_swapModes($restore_mode, $restore_class);
  424.  
  425.         return $result;
  426.     }
  427.  
  428.  
  429.     /**
  430.      * Selects rows as a DB_Result/MDB2_Result_* object.
  431.      *
  432.      * @param string $query  The name of the SQL SELECT to use from the
  433.      *                       $this->sql property array.
  434.      * @param string $filter SQL snippet to AND to the default WHERE clause
  435.      * @param string $order  SQL snippet to override default ORDER BY clause
  436.      * @param int    $start  The record number from which to start result set
  437.      * @param int    $count  The number of records to list in result set.
  438.      * @param array $params  Parameters for placeholder substitutions, if any.
  439.      * @return object DB_Result/MDB2_Result_* object on success
  440.      *                (PEAR_Error on failure)
  441.      * @see DB_Table::_swapModes()
  442.      * @access public
  443.      */
  444.     function selectResult($query, $filter = null, $order = null,
  445.                    $start = null, $count = null, $params = array())
  446.     {
  447.         // Is $query a query array or a key of $this->sql ?
  448.         // On output from this block, $query is an array
  449.         if (!is_array($query)) {
  450.             if (is_string($query)) {
  451.                 if (isset($this->sql[$query])) {
  452.                     $query = $this->sql[$query];
  453.                 } else {
  454.                     return $this->throwError(
  455.                            constant($this->_primary_subclass . '_ERR_SQL_UNDEF'),
  456.                            $query);
  457.                 }
  458.             } else {
  459.                 return $this->throwError(
  460.                        constant($this->_primary_subclass . '_ERR_SQL_NOT_STRING'));
  461.             }
  462.         }
  463.        
  464.         // build the base command
  465.         $sql = $this->buildSQL($query, $filter, $order, $start, $count);
  466.         if (PEAR::isError($sql)) {
  467.             return $sql;
  468.         }
  469.  
  470.         // DB_Table assumes you are using a shared PEAR DB/MDB2 object.
  471.         // Record fetchmode settings, to be restored afterwards.
  472.         $db =& $this->db;
  473.         $restore_mode = $db->fetchmode;
  474.         if ($this->backend == 'mdb2') {
  475.             $restore_class = $db->getOption('fetch_class');
  476.         } else {
  477.             $restore_class = $db->fetchmode_object_class;
  478.         }
  479.  
  480.         // swap modes
  481.         $fetchmode = $this->fetchmode;
  482.         $fetchmode_object_class = $this->fetchmode_object_class;
  483.         if (isset($query['fetchmode'])) {
  484.             $fetchmode = $query['fetchmode'];
  485.         }
  486.         if (isset($query['fetchmode_object_class'])) {
  487.             $fetchmode_object_class = $query['fetchmode_object_class'];
  488.         }
  489.         $this->_swapModes($fetchmode, $fetchmode_object_class);
  490.  
  491.         // make sure params is an array
  492.         if (!is_null($params)) {
  493.             $params = (array) $params;
  494.         }
  495.  
  496.         // get the result
  497.         if ($this->backend == 'mdb2') {
  498.             $stmt =& $db->prepare($sql);
  499.             if (PEAR::isError($stmt)) {
  500.                 return $stmt;
  501.             }
  502.             $result =& $stmt->execute($params);
  503.         } else {
  504.             $result =& $db->query($sql, $params);
  505.         }
  506.  
  507.         // swap modes back
  508.         $this->_swapModes($restore_mode, $restore_class);
  509.  
  510.         // return the result
  511.         return $result;
  512.     }
  513.  
  514.  
  515.     /**
  516.      * Counts the number of rows which will be returned by a query.
  517.      *
  518.      * This function works identically to {@link select()}, but it
  519.      * returns the number of rows returned by a query instead of the
  520.      * query results themselves.
  521.      *
  522.      * @author Ian Eure <ian@php.net>
  523.      * @param string $query  The name of the SQL SELECT to use from the
  524.      *                       $this->sql property array.
  525.      * @param string $filter Ad-hoc SQL snippet to AND with the default
  526.      *                       SELECT WHERE clause.
  527.      * @param string $order  Ad-hoc SQL snippet to override the default
  528.      *                       SELECT ORDER BY clause.
  529.      * @param int    $start  Row number from which to start listing in result
  530.      * @param int    $count  Number of rows to list in result set
  531.      * @param array  $params Parameters to use in placeholder substitutions
  532.      *                       (if any).
  533.      * @return int   Number of records from the table (or PEAR_Error on failure)
  534.      *
  535.      * @see DB_Table::select()
  536.      * @access public
  537.      */
  538.     function selectCount($query, $filter = null, $order = null,
  539.                        $start = null, $count = null, $params = array())
  540.     {
  541.  
  542.         // Is $query a query array or a key of $this->sql ?
  543.         if (is_array($query)) {
  544.             $sql_key = null;
  545.             $count_query = $query;
  546.         } else {
  547.             if (is_string($query)) {
  548.                 if (isset($this->sql[$query])) {
  549.                     $sql_key = $query;
  550.                     $count_query = $this->sql[$query];
  551.                 } else {
  552.                     return $this->throwError(
  553.                            constant($this->_primary_subclass . '_ERR_SQL_UNDEF'), 
  554.                            $query);
  555.                 }
  556.             } else {
  557.                 return $this->throwError(
  558.                        constant($this->_primary_subclass . '_ERR_SQL_NOT_STRING'));
  559.             }
  560.         }
  561.  
  562.         // Use Table name as default 'from' if child class is DB_TABLE
  563.         if ($this->_primary_subclass == 'DB_TABLE') {
  564.             if (!isset($query['from'])) {
  565.                 $count_query['from'] = $this->table;
  566.             }
  567.         }
  568.  
  569.         // If the query is a stored query in $this->sql, then create a corresponding
  570.         // key for the count query, or check if the count-query already exists
  571.         $ready = false;
  572.         if ($sql_key) {
  573.             // Create an sql key name for this count-query
  574.             $count_key = '__count_' . $sql_key;
  575.             // Check if a this count query alread exists in $this->sql
  576.             if (isset($this->sql[$count_key])) {
  577.                 $ready = true;
  578.             }
  579.         }
  580.  
  581.         // If a count-query does not already exist, create $count_query array
  582.         if ($ready) {
  583.  
  584.             $count_query = $this->sql[$count_key];
  585.  
  586.         } else {
  587.  
  588.             // Is a count-field set for the query?
  589.             if (!isset($count_query['count']) || 
  590.                 trim($count_query['count']) == '') {
  591.                 $count_query['count'] = '*';
  592.             }
  593.  
  594.             // Replace the SELECT fields with a COUNT() command
  595.             $count_query['select'] = "COUNT({$count_query['count']})";
  596.  
  597.             // Replace the 'get' key so we only get one result item
  598.             $count_query['get'] = 'one';
  599.  
  600.             // Create a new count-query in $this->sql
  601.             if ($sql_key) {
  602.                 $this->sql[$count_key] = $count_query;
  603.             }
  604.  
  605.         }
  606.  
  607.         // Retrieve the count results
  608.         return $this->select($count_query, $filter, $order,
  609.                              $start, $count, $params);
  610.  
  611.     }
  612.  
  613.     /**
  614.      * Changes the $this->db PEAR DB/MDB2 object fetchmode and
  615.      * fetchmode_object_class.
  616.      *
  617.      * @param string $new_mode A DB/MDB2_FETCHMODE_* constant.  If null,
  618.      * defaults to whatever the DB/MDB2 object is currently using.
  619.      *
  620.      * @param string $new_class The object class to use for results when
  621.      * the $db object is in DB/MDB2_FETCHMODE_OBJECT fetch mode.  If null,
  622.      * defaults to whatever the the DB/MDB2 object is currently using.
  623.      *
  624.      * @return void
  625.      * @access private
  626.      */
  627.     function _swapModes($new_mode, $new_class)
  628.     {
  629.         // get the old (current) mode and class
  630.         $db =& $this->db;
  631.         $old_mode = $db->fetchmode;
  632.         if ($this->backend == 'mdb2') {
  633.             $old_class = $db->getOption('fetch_class');
  634.         } else {
  635.             $old_class = $db->fetchmode_object_class;
  636.         }
  637.  
  638.         // don't need to swap anything if the new modes are both
  639.         // null or if the old and new modes already match.
  640.         if ((is_null($new_mode) && is_null($new_class)) ||
  641.             ($old_mode == $new_mode && $old_class == $new_class)) {
  642.             return;
  643.         }
  644.  
  645.         // set the default new mode
  646.         if (is_null($new_mode)) {
  647.             $new_mode = $old_mode;
  648.         }
  649.  
  650.         // set the default new class
  651.         if (is_null($new_class)) {
  652.             $new_class = $old_class;
  653.         }
  654.  
  655.         // swap modes
  656.         $db->setFetchMode($new_mode, $new_class);
  657.     }
  658.  
  659.  
  660.     /**
  661.      * Returns SQL condition equating columns to literal values.
  662.      *
  663.      * The parameter $data is an associative array in which keys are
  664.      * column names and values are corresponding values. The method
  665.      * returns an SQL string that is true if the value of every 
  666.      * specified database columns is equal to the corresponding 
  667.      * value in $data. 
  668.      * 
  669.      * For example, if:
  670.      * <code>
  671.      *     $data = array( 'c1' => 'thing', 'c2' => 23, 'c3' => 0.32 )
  672.      * </code>
  673.      * then buildFilter($data) returns a string 
  674.      * <code>
  675.      *     c1 => 'thing' AND c2 => 23 AND c3 = 0.32
  676.      * </code>
  677.      * in which string values are replaced by SQL literal values, 
  678.      * quoted and escaped as necessary.
  679.      * 
  680.      * Values are quoted and escaped as appropriate for each data 
  681.      * type and the backend RDBMS, using the MDB2::quote() or
  682.      * DB::smartQuote() method. The behavior depends on the PHP type
  683.      * of the value: string values are quoted and escaped, while 
  684.      * integer and float numerical values are not. Boolean values
  685.      * in $data are represented as 0 or 1, consistent with the way 
  686.      * booleans are stored by DB_Table. 
  687.      *
  688.      * Null values: The treatment of null values in $data depends upon 
  689.      * the value of the $match parameter . If $match == 'simple', an 
  690.      * empty string is returned if any $value of $data with a key in 
  691.      * $data_key is null. If $match == 'partial', the returned SQL 
  692.      * expression equates only the relevant non-null values of $data 
  693.      * to the values of corresponding database columns. If 
  694.      * $match == 'full', the function returns an empty string if all 
  695.      * of the relevant values of data are null, and returns a 
  696.      * PEAR_Error if some of the selected values are null and others 
  697.      * are not null.
  698.      *
  699.      * @param array $data associative array, keys are column names
  700.      * @return string SQL expression equating values in $data to 
  701.      *                values of columns named by keys.
  702.      * @access public
  703.      */
  704.     function buildFilter($data, $match = 'simple')
  705.     {
  706.         // Check $match type value
  707.         if (!in_array($match, array('simple', 'partial', 'full'))) {
  708.             return $this->throwError(
  709.                             DB_TABLE_DATABASE_ERR_MATCH_TYPE);
  710.         }
  711.  
  712.         if (count($data) == 0) {
  713.             return '';
  714.         }
  715.         $filter = array();
  716.         foreach ($data as $key => $value) {
  717.             if (!is_null($value)) {
  718.                 if ($match == 'full' && isset($found_null)) {
  719.                     return $this->throwError(
  720.                               DB_TABLE_DATABASE_ERR_FULL_KEY);
  721.                 }
  722.                 if (is_bool($value)) {
  723.                    $value = $value ? '1' : '0';
  724.                 } else {
  725.                     if ($this->backend == 'mdb2') {
  726.                         $value = $this->db->quote($value);
  727.                     } else {
  728.                         $value = $this->db->quoteSmart($value);
  729.                     }
  730.                 }
  731.                 $filter[] = "$key = $value";
  732.             } else {
  733.                 if ($match == 'simple') {
  734.                     return ''; // if any value in $data is null
  735.                 } elseif ($match == 'full') {
  736.                     $found_null = true;
  737.                 }
  738.             }
  739.         }
  740.         return implode(' AND ', $filter);
  741.     }
  742.  
  743.     // }}}
  744. }
  745.  
  746. // }}}
  747.  
  748. /* Local variables:
  749.  * tab-width: 4
  750.  * c-basic-offset: 4
  751.  * c-hanging-comment-ender-p: nil
  752.  * End:
  753.  */
  754.  
  755. ?>
  756.