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

Source for file common.php

Documentation is available at common.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: Stig Bakken <ssb@php.net>                                    |
  17. // |         Tomas V.V.Cox <cox@idecnet.com>                              |
  18. // | Maintainer: Daniel Convissor <danielc@php.net>                       |
  19. // +----------------------------------------------------------------------+
  20. //
  21. // $Id: common.php,v 1.99 2004/04/07 04:56:58 danielc Exp $
  22.  
  23. require_once 'PEAR.php';
  24.  
  25. /**
  26.  * DB_common is a base class for DB implementations, and must be
  27.  * inherited by all such
  28.  *
  29.  * @package  DB
  30.  * @version  $Id: common.php,v 1.99 2004/04/07 04:56:58 danielc Exp $
  31.  * @category Database
  32.  * @author   Stig Bakken <ssb@php.net>
  33.  * @author   Tomas V.V.Cox <cox@idecnet.com>
  34.  */
  35. class DB_common extends PEAR
  36. {
  37.     // {{{ properties
  38.  
  39.     /**
  40.      * assoc of capabilities for this DB implementation
  41.      * $features['limit'] =>  'emulate' => emulate with fetch row by number
  42.      *                        'alter'   => alter the query
  43.      *                        false     => skip rows
  44.      * @var array 
  45.      */
  46.     var $features = array();
  47.  
  48.     /**
  49.      * assoc mapping native error codes to DB ones
  50.      * @var array 
  51.      */
  52.     var $errorcode_map = array();
  53.  
  54.     /**
  55.      * DB type (mysql, oci8, odbc etc.)
  56.      * @var string 
  57.      */
  58.     var $phptype;
  59.  
  60.     /**
  61.      * @var string 
  62.      */
  63.     var $prepare_tokens;
  64.  
  65.     /**
  66.      * @var string 
  67.      */
  68.     var $prepare_types;
  69.  
  70.     /**
  71.      * @var string 
  72.      */
  73.     var $prepared_queries;
  74.  
  75.     /**
  76.      * @var integer 
  77.      */
  78.     var $prepare_maxstmt = 0;
  79.  
  80.     /**
  81.      * @var string 
  82.      */
  83.     var $last_query = '';
  84.  
  85.     /**
  86.      * @var integer 
  87.      */
  88.     var $fetchmode = DB_FETCHMODE_ORDERED;
  89.  
  90.     /**
  91.      * @var string 
  92.      */
  93.     var $fetchmode_object_class = 'stdClass';
  94.  
  95.     /**
  96.      * Run-time configuration options.
  97.      *
  98.      * The 'optimize' option has been deprecated.  Use the 'portability'
  99.      * option instead.
  100.      *
  101.      * @see DB_common::setOption()
  102.      * @var array 
  103.      */
  104.     var $options = array(
  105.         'persistent' => false,
  106.         'ssl' => false,
  107.         'debug' => 0,
  108.         'seqname_format' => '%s_seq',
  109.         'autofree' => false,
  110.         'portability' => DB_PORTABILITY_NONE,
  111.         'optimize' => 'performance',  // Deprecated.  Use 'portability'.
  112.     );
  113.  
  114.     /**
  115.      * DB handle
  116.      * @var resource 
  117.      */
  118.     var $dbh;
  119.  
  120.     // }}}
  121.     // {{{ toString()
  122.  
  123.     /**
  124.      * String conversation
  125.      *
  126.      * @return string 
  127.      * @access private
  128.      */
  129.     function toString()
  130.     {
  131.         $info strtolower(get_class($this));
  132.         $info .=  ': (phptype=' $this->phptype .
  133.                   ', dbsyntax=' $this->dbsyntax .
  134.                   ')';
  135.  
  136.         if ($this->connection{
  137.             $info .= ' [connected]';
  138.         }
  139.  
  140.         return $info;
  141.     }
  142.  
  143.     // }}}
  144.     // {{{ constructor
  145.  
  146.     /**
  147.      * Constructor
  148.      */
  149.     function DB_common()
  150.     {
  151.         $this->PEAR('DB_Error');
  152.     }
  153.  
  154.     // }}}
  155.     // {{{ quoteString()
  156.  
  157.     /**
  158.      * DEPRECATED: Quotes a string so it can be safely used within string
  159.      * delimiters in a query
  160.      *
  161.      * @return string quoted string
  162.      *
  163.      * @see DB_common::quoteSmart(), DB_common::escapeSimple()
  164.      * @deprecated  Deprecated in release 1.2 or lower
  165.      * @internal
  166.      */
  167.     function quoteString($string)
  168.     {
  169.         $string $this->quote($string);
  170.         if ($string{0== "'"{
  171.             return substr($string1-1);
  172.         }
  173.         return $string;
  174.     }
  175.  
  176.     // }}}
  177.     // {{{ quote()
  178.  
  179.     /**
  180.      * DEPRECATED: Quotes a string so it can be safely used in a query
  181.      *
  182.      * @param string $string the input string to quote
  183.      *
  184.      * @return string The NULL string or the string quotes
  185.      *                 in magic_quote_sybase style
  186.      *
  187.      * @see DB_common::quoteSmart(), DB_common::escapeSimple()
  188.      * @deprecated  Deprecated in release 1.6.0
  189.      * @internal
  190.      */
  191.     function quote($string = null)
  192.     {
  193.         return ($string === null'NULL' "'".str_replace("'""''"$string)."'";
  194.     }
  195.  
  196.     // }}}
  197.     // {{{ quoteIdentifier()
  198.  
  199.     /**
  200.      * Quote a string so it can be safely used as a table or column name
  201.      *
  202.      * Delimiting style depends on which database driver is being used.
  203.      *
  204.      * NOTE: just because you CAN use delimited identifiers doesn't mean
  205.      * you SHOULD use them.  In general, they end up causing way more
  206.      * problems than they solve.
  207.      *
  208.      * Portability is broken by using the following characters inside
  209.      * delimited identifiers:
  210.      *   + backtick (<kbd>`</kbd>) -- due to MySQL
  211.      *   + double quote (<kbd>"</kbd>) -- due to Oracle
  212.      *   + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
  213.      *
  214.      * Delimited identifiers are known to generally work correctly under
  215.      * the following drivers:
  216.      *   + mssql
  217.      *   + mysql
  218.      *   + mysqli
  219.      *   + oci8
  220.      *   + odbc(access)
  221.      *   + odbc(db2)
  222.      *   + pgsql
  223.      *   + sqlite
  224.      *   + sybase
  225.      *
  226.      * InterBase doesn't seem to be able to use delimited identifiers
  227.      * via PHP 4.  They work fine under PHP 5.
  228.      *
  229.      * @param string $str  identifier name to be quoted
  230.      *
  231.      * @return string  quoted identifier string
  232.      *
  233.      * @since 1.6.0
  234.      * @access public
  235.      */
  236.     function quoteIdentifier($str)
  237.     {
  238.         return '"' str_replace('"''""'$str'"';
  239.     }
  240.  
  241.     // }}}
  242.     // {{{ quoteSmart()
  243.  
  244.     /**
  245.      * Format input so it can be safely used in a query
  246.      *
  247.      * The output depends on the PHP data type of input and the database
  248.      * type being used.
  249.      *
  250.      * @param mixed $in  data to be quoted
  251.      *
  252.      * @return mixed  the format of the results depends on the input's
  253.      *                 PHP type:
  254.      *
  255.      *  <ul>
  256.      *   <li>
  257.      *     <kbd>input</kbd> -> <samp>returns</samp>
  258.      *   </li>
  259.      *   <li>
  260.      *     <kbd>null</kbd> -> the string <samp>NULL</samp>
  261.      *   </li>
  262.      *   <li>
  263.      *     <kbd>integer</kbd> or <kbd>double</kbd> -> the unquoted number
  264.      *   </li>
  265.      *   <li>
  266.      *     &type.bool; -> output depends on the driver in use
  267.      *     Most drivers return integers: <samp>1</samp> if
  268.      *     <kbd>true</kbd> or <samp>0</samp> if
  269.      *     <kbd>false</kbd>.
  270.      *     Some return strings: <samp>TRUE</samp> if
  271.      *     <kbd>true</kbd> or <samp>FALSE</samp> if
  272.      *     <kbd>false</kbd>.
  273.      *     Finally one returns strings: <samp>T</samp> if
  274.      *     <kbd>true</kbd> or <samp>F</samp> if
  275.      *     <kbd>false</kbd>. Here is a list of each DBMS,
  276.      *     the values returned and the suggested column type:
  277.      *     <ul>
  278.      *       <li>
  279.      *         <kbd>dbase</kbd> -> <samp>T/F</samp>
  280.      *         (<kbd>Logical</kbd>)
  281.      *       </li>
  282.      *       <li>
  283.      *         <kbd>fbase</kbd> -> <samp>TRUE/FALSE</samp>
  284.      *         (<kbd>BOOLEAN</kbd>)
  285.      *       </li>
  286.      *       <li>
  287.      *         <kbd>ibase</kbd> -> <samp>1/0</samp>
  288.      *         (<kbd>SMALLINT</kbd>) [1]
  289.      *       </li>
  290.      *       <li>
  291.      *         <kbd>ifx</kbd> -> <samp>1/0</samp>
  292.      *         (<kbd>SMALLINT</kbd>) [1]
  293.      *       </li>
  294.      *       <li>
  295.      *         <kbd>msql</kbd> -> <samp>1/0</samp>
  296.      *         (<kbd>INTEGER</kbd>)
  297.      *       </li>
  298.      *       <li>
  299.      *         <kbd>mssql</kbd> -> <samp>1/0</samp>
  300.      *         (<kbd>BIT</kbd>)
  301.      *       </li>
  302.      *       <li>
  303.      *         <kbd>mysql</kbd> -> <samp>1/0</samp>
  304.      *         (<kbd>TINYINT(1)</kbd>)
  305.      *       </li>
  306.      *       <li>
  307.      *         <kbd>mysqli</kbd> -> <samp>1/0</samp>
  308.      *         (<kbd>TINYINT(1)</kbd>)
  309.      *       </li>
  310.      *       <li>
  311.      *         <kbd>oci8</kbd> -> <samp>1/0</samp>
  312.      *         (<kbd>NUMBER(1)</kbd>)
  313.      *       </li>
  314.      *       <li>
  315.      *         <kbd>odbc</kbd> -> <samp>1/0</samp>
  316.      *         (<kbd>SMALLINT</kbd>) [1]
  317.      *       </li>
  318.      *       <li>
  319.      *         <kbd>pgsql</kbd> -> <samp>TRUE/FALSE</samp>
  320.      *         (<kbd>BOOLEAN</kbd>)
  321.      *       </li>
  322.      *       <li>
  323.      *         <kbd>sqlite</kbd> -> <samp>1/0</samp>
  324.      *         (<kbd>INTEGER</kbd>)
  325.      *       </li>
  326.      *       <li>
  327.      *         <kbd>sybase</kbd> -> <samp>1/0</samp>
  328.      *         (<kbd>TINYINT(1)</kbd>)
  329.      *       </li>
  330.      *     </ul>
  331.      *     [1] Accommodate the lowest common denominator because not all
  332.      *     versions of have <kbd>BOOLEAN</kbd>.
  333.      *   </li>
  334.      *   <li>
  335.      *     other (including strings and numeric strings) ->
  336.      *     the data with single quotes escaped by preceeding
  337.      *     single quotes, backslashes are escaped by preceeding
  338.      *     backslashes, then the whole string is encapsulated
  339.      *     between single quotes
  340.      *   </li>
  341.      *  </ul>
  342.      *
  343.      * @since 1.6.0
  344.      * @see DB_common::escapeSimple()
  345.      * @access public
  346.      */
  347.     function quoteSmart($in)
  348.     {
  349.         if (is_int($in|| is_double($in)) {
  350.             return $in;
  351.         elseif (is_bool($in)) {
  352.             return $in ? 1 : 0;
  353.         elseif (is_null($in)) {
  354.             return 'NULL';
  355.         else {
  356.             return "'" $this->escapeSimple($in"'";
  357.         }
  358.     }
  359.  
  360.     // }}}
  361.     // {{{ escapeSimple()
  362.  
  363.     /**
  364.      * Escape a string according to the current DBMS's standards
  365.      *
  366.      * In SQLite, this makes things safe for inserts/updates, but may
  367.      * cause problems when performing text comparisons against columns
  368.      * containing binary data. See the
  369.      * {@link http://php.net/sqlite_escape_string PHP manual} for more info.
  370.      *
  371.      * @param string $str  the string to be escaped
  372.      *
  373.      * @return string  the escaped string
  374.      *
  375.      * @since 1.6.0
  376.      * @see DB_common::quoteSmart()
  377.      * @access public
  378.      */
  379.     function escapeSimple($str{
  380.         return str_replace("'""''"$str);
  381.     }
  382.  
  383.     // }}}
  384.     // {{{ provides()
  385.  
  386.     /**
  387.      * Tell whether a DB implementation or its backend extension
  388.      * supports a given feature
  389.      *
  390.      * @param array $feature name of the feature (see the DB class doc)
  391.      * @return bool whether this DB implementation supports $feature
  392.      * @access public
  393.      */
  394.     function provides($feature)
  395.     {
  396.         return $this->features[$feature];
  397.     }
  398.  
  399.     // }}}
  400.     // {{{ errorCode()
  401.  
  402.     /**
  403.      * Map native error codes to DB's portable ones
  404.      *
  405.      * Requires that the DB implementation's constructor fills
  406.      * in the <var>$errorcode_map</var> property.
  407.      *
  408.      * @param mixed  $nativecode  the native error code, as returned by the
  409.      *  backend database extension (string or integer)
  410.      *
  411.      * @return int a portable DB error code, or DB_ERROR if this DB
  412.      *  implementation has no mapping for the given error code.
  413.      *
  414.      * @access public
  415.      */
  416.     function errorCode($nativecode)
  417.     {
  418.         if (isset($this->errorcode_map[$nativecode])) {
  419.             return $this->errorcode_map[$nativecode];
  420.         }
  421.         // Fall back to DB_ERROR if there was no mapping.
  422.         return DB_ERROR;
  423.     }
  424.  
  425.     // }}}
  426.     // {{{ errorMessage()
  427.  
  428.     /**
  429.      * Map a DB error code to a textual message.  This is actually
  430.      * just a wrapper for DB::errorMessage()
  431.      *
  432.      * @param integer $dbcode the DB error code
  433.      *
  434.      * @return string the corresponding error message, of false
  435.      *  if the error code was unknown
  436.      *
  437.      * @access public
  438.      */
  439.     function errorMessage($dbcode)
  440.     {
  441.         return DB::errorMessage($this->errorcode_map[$dbcode]);
  442.     }
  443.  
  444.     // }}}
  445.     // {{{ raiseError()
  446.  
  447.     /**
  448.      * Communicate an error and invoke error callbacks, etc
  449.      *
  450.      * Basically a wrapper for PEAR::raiseError without the message string.
  451.      *
  452.      * @param mixed    integer error code, or a PEAR error object (all
  453.      *                  other parameters are ignored if this parameter is
  454.      *                  an object
  455.      *
  456.      * @param int      error mode, see PEAR_Error docs
  457.      *
  458.      * @param mixed    If error mode is PEAR_ERROR_TRIGGER, this is the
  459.      *                  error level (E_USER_NOTICE etc).  If error mode is
  460.      *                  PEAR_ERROR_CALLBACK, this is the callback function,
  461.      *                  either as a function name, or as an array of an
  462.      *                  object and method name.  For other error modes this
  463.      *                  parameter is ignored.
  464.      *
  465.      * @param string   Extra debug information.  Defaults to the last
  466.      *                  query and native error code.
  467.      *
  468.      * @param mixed    Native error code, integer or string depending the
  469.      *                  backend.
  470.      *
  471.      * @return object  PEAR error object
  472.      *
  473.      * @access public
  474.      * @see PEAR_Error
  475.      */
  476.     function &raiseError($code = DB_ERROR$mode = null$options = null,
  477.                          $userinfo = null$nativecode = null)
  478.     {
  479.         // The error is yet a DB error object
  480.         if (is_object($code)) {
  481.             // because we the static PEAR::raiseError, our global
  482.             // handler should be used if it is set
  483.             if ($mode === null && !empty($this->_default_error_mode)) {
  484.                 $mode    $this->_default_error_mode;
  485.                 $options $this->_default_error_options;
  486.             }
  487.             $tmp = PEAR::raiseError($codenull$mode$optionsnullnulltrue);
  488.             return $tmp;
  489.         }
  490.  
  491.         if ($userinfo === null{
  492.             $userinfo $this->last_query;
  493.         }
  494.  
  495.         if ($nativecode{
  496.             $userinfo .= ' [nativecode=' trim($nativecode']';
  497.         }
  498.  
  499.         $tmp = PEAR::raiseError(null$code$mode$options$userinfo,
  500.                                 'DB_Error'true);
  501.         return $tmp;
  502.     }
  503.  
  504.     // }}}
  505.     // {{{ setFetchMode()
  506.  
  507.     /**
  508.      * Sets which fetch mode should be used by default on queries
  509.      * on this connection
  510.      *
  511.      * @param integer $fetchmode DB_FETCHMODE_ORDERED or
  512.      *         DB_FETCHMODE_ASSOC, possibly bit-wise OR'ed with
  513.      *         DB_FETCHMODE_FLIPPED.
  514.      *
  515.      * @param string $object_class The class of the object
  516.      *                       to be returned by the fetch methods when
  517.      *                       the DB_FETCHMODE_OBJECT mode is selected.
  518.      *                       If no class is specified by default a cast
  519.      *                       to object from the assoc array row will be done.
  520.      *                       There is also the posibility to use and extend the
  521.      *                       'DB_row' class.
  522.      *
  523.      * @see DB_FETCHMODE_ORDERED
  524.      * @see DB_FETCHMODE_ASSOC
  525.      * @see DB_FETCHMODE_FLIPPED
  526.      * @see DB_FETCHMODE_OBJECT
  527.      * @see DB_row::DB_row()
  528.      * @access public
  529.      */
  530.     function setFetchMode($fetchmode$object_class 'stdClass')
  531.     {
  532.         switch ($fetchmode{
  533.             case DB_FETCHMODE_OBJECT:
  534.                 $this->fetchmode_object_class = $object_class;
  535.             case DB_FETCHMODE_ORDERED:
  536.             case DB_FETCHMODE_ASSOC:
  537.                 $this->fetchmode = $fetchmode;
  538.                 break;
  539.             default:
  540.                 return $this->raiseError('invalid fetchmode mode');
  541.         }
  542.     }
  543.  
  544.     // }}}
  545.     // {{{ setOption()
  546.  
  547.     /**
  548.      * Set run-time configuration options for PEAR DB
  549.      *
  550.      * Options, their data types, default values and description:
  551.      * <ul>
  552.      * <li>
  553.      * <var>autofree</var> <kbd>boolean</kbd> = <samp>false</samp>
  554.      *      <br />should results be freed automatically when there are no
  555.      *            more rows?
  556.      * </li><li>
  557.      * <var>debug</var> <kbd>integer</kbd> = <samp>0</samp>
  558.      *      <br />debug level
  559.      * </li><li>
  560.      * <var>persistent</var> <kbd>boolean</kbd> = <samp>false</samp>
  561.      *      <br />should the connection be persistent?
  562.      * </li><li>
  563.      * <var>portability</var> <kbd>integer</kbd> = <samp>DB_PORTABILITY_NONE</samp>
  564.      *      <br />portability mode constant (see below)
  565.      * </li><li>
  566.      * <var>seqname_format</var> <kbd>string</kbd> = <samp>%s_seq</samp>
  567.      *      <br />the sprintf() format string used on sequence names.  This
  568.      *            format is applied to sequence names passed to
  569.      *            createSequence(), nextID() and dropSequence().
  570.      * </li><li>
  571.      * <var>ssl</var> <kbd>boolean</kbd> = <samp>false</samp>
  572.      *      <br />use ssl to connect?
  573.      * </li>
  574.      * </ul>
  575.      *
  576.      * -----------------------------------------
  577.      *
  578.      * PORTABILITY MODES
  579.      *
  580.      * These modes are bitwised, so they can be combined using <kbd>|</kbd>
  581.      * and removed using <kbd>^</kbd>.  See the examples section below on how
  582.      * to do this.
  583.      *
  584.      * <samp>DB_PORTABILITY_NONE</samp>
  585.      * turn off all portability features
  586.      *
  587.      * This mode gets automatically turned on if the deprecated
  588.      * <var>optimize</var> option gets set to <samp>performance</samp>.
  589.      *
  590.      *
  591.      * <samp>DB_PORTABILITY_LOWERCASE</samp>
  592.      * convert names of tables and fields to lower case when using
  593.      * <kbd>get*()</kbd>, <kbd>fetch*()</kbd> and <kbd>tableInfo()</kbd>
  594.      *
  595.      * This mode gets automatically turned on in the following databases
  596.      * if the deprecated option <var>optimize</var> gets set to
  597.      * <samp>portability</samp>:
  598.      * + oci8
  599.      *
  600.      *
  601.      * <samp>DB_PORTABILITY_RTRIM</samp>
  602.      * right trim the data output by <kbd>get*()</kbd> <kbd>fetch*()</kbd>
  603.      *
  604.      *
  605.      * <samp>DB_PORTABILITY_DELETE_COUNT</samp>
  606.      * force reporting the number of rows deleted
  607.      *
  608.      * Some DBMS's don't count the number of rows deleted when performing
  609.      * simple <kbd>DELETE FROM tablename</kbd> queries.  This portability
  610.      * mode tricks such DBMS's into telling the count by adding
  611.      * <samp>WHERE 1=1</samp> to the end of <kbd>DELETE</kbd> queries.
  612.      *
  613.      * This mode gets automatically turned on in the following databases
  614.      * if the deprecated option <var>optimize</var> gets set to
  615.      * <samp>portability</samp>:
  616.      * + fbsql
  617.      * + mysql
  618.      * + mysqli
  619.      * + sqlite
  620.      *
  621.      *
  622.      * <samp>DB_PORTABILITY_NUMROWS</samp>
  623.      * enable hack that makes <kbd>numRows()</kbd> work in Oracle
  624.      *
  625.      * This mode gets automatically turned on in the following databases
  626.      * if the deprecated option <var>optimize</var> gets set to
  627.      * <samp>portability</samp>:
  628.      * + oci8
  629.      *
  630.      *
  631.      * <samp>DB_PORTABILITY_ERRORS</samp>
  632.      * makes certain error messages in certain drivers compatible
  633.      * with those from other DBMS's
  634.      *
  635.      * + mysql, mysqli:  change unique/primary key constraints
  636.      *   DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT
  637.      *
  638.      * + odbc(access):  MS's ODBC driver reports 'no such field' as code
  639.      *   07001, which means 'too few parameters.'  When this option is on
  640.      *   that code gets mapped to DB_ERROR_NOSUCHFIELD.
  641.      *   DB_ERROR_MISMATCH -> DB_ERROR_NOSUCHFIELD
  642.      *
  643.      *
  644.      * <samp>DB_PORTABILITY_NULL_TO_EMPTY</samp>
  645.      * convert null values to empty strings in data output by get*() and
  646.      * fetch*().  Needed because Oracle considers empty strings to be null,
  647.      * while most other DBMS's know the difference between empty and null.
  648.      *
  649.      *
  650.      * <samp>DB_PORTABILITY_ALL</samp>
  651.      * turn on all portability features
  652.      *
  653.      * -----------------------------------------
  654.      *
  655.      * Example 1. Simple setOption() example
  656.      * <code> <?php
  657.      * $dbh->setOption('autofree', true);
  658.      * ?></code>
  659.      *
  660.      * Example 2. Portability for lowercasing and trimming
  661.      * <code> <?php
  662.      * $dbh->setOption('portability',
  663.      *                  DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_RTRIM);
  664.      * ?></code>
  665.      *
  666.      * Example 3. All portability options except trimming
  667.      * <code> <?php
  668.      * $dbh->setOption('portability',
  669.      *                  DB_PORTABILITY_ALL ^ DB_PORTABILITY_RTRIM);
  670.      * ?></code>
  671.      *
  672.      * @param string $option option name
  673.      * @param mixed  $value value for the option
  674.      *
  675.      * @return int  DB_OK on success.  DB_Error object on failure.
  676.      *
  677.      * @see DB_common::$options
  678.      */
  679.     function setOption($option$value)
  680.     {
  681.         if (isset($this->options[$option])) {
  682.             $this->options[$option$value;
  683.  
  684.             /*
  685.              * Backwards compatibility check for the deprecated 'optimize'
  686.              * option.  Done here in case settings change after connecting.
  687.              */
  688.             if ($option == 'optimize'{
  689.                 if ($value == 'portability'{
  690.                     switch ($this->phptype{
  691.                         case 'oci8':
  692.                             $this->options['portability'=
  693.                                     DB_PORTABILITY_LOWERCASE |
  694.                                     DB_PORTABILITY_NUMROWS;
  695.                             break;
  696.                         case 'fbsql':
  697.                         case 'mysql':
  698.                         case 'mysqli':
  699.                         case 'sqlite':
  700.                             $this->options['portability'=
  701.                                     DB_PORTABILITY_DELETE_COUNT;
  702.                             break;
  703.                     }
  704.                 else {
  705.                     $this->options['portability'DB_PORTABILITY_NONE;
  706.                 }
  707.             }
  708.  
  709.             return DB_OK;
  710.         }
  711.         return $this->raiseError("unknown option $option");
  712.     }
  713.  
  714.     // }}}
  715.     // {{{ getOption()
  716.  
  717.     /**
  718.      * Returns the value of an option
  719.      *
  720.      * @param string $option option name
  721.      *
  722.      * @return mixed the option value
  723.      */
  724.     function getOption($option)
  725.     {
  726.         if (isset($this->options[$option])) {
  727.             return $this->options[$option];
  728.         }
  729.         return $this->raiseError("unknown option $option");
  730.     }
  731.  
  732.     // }}}
  733.     // {{{ prepare()
  734.  
  735.     /**
  736.      * Prepares a query for multiple execution with execute()
  737.      *
  738.      * Creates a query that can be run multiple times.  Each time it is run,
  739.      * the placeholders, if any, will be replaced by the contents of
  740.      * execute()'s $data argument.
  741.      *
  742.      * Three types of placeholders can be used:
  743.      *   + <kbd>?</kbd>  scalar value (i.e. strings, integers).  The system
  744.      *                   will automatically quote and escape the data.
  745.      *   + <kbd>!</kbd>  value is inserted 'as is'
  746.      *   + <kbd>&</kbd>  requires a file name.  The file's contents get
  747.      *                   inserted into the query (i.e. saving binary
  748.      *                   data in a db)
  749.      *
  750.      * Example 1.
  751.      * <code> <?php
  752.      * $sth = $dbh->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)');
  753.      * $data = array(
  754.      *     "John's text",
  755.      *     "'it''s good'",
  756.      *     'filename.txt'
  757.      * );
  758.      * $res = $dbh->execute($sth, $data);
  759.      * ?></code>
  760.      *
  761.      * Use backslashes to escape placeholder characters if you don't want
  762.      * them to be interpreted as placeholders:
  763.      * <pre>
  764.      *    "UPDATE foo SET col=? WHERE col='over \& under'"
  765.      * </pre>
  766.      *
  767.      * With some database backends, this is emulated.
  768.      *
  769.      * {@internal ibase and oci8 have their own prepare() methods.}}
  770.      *
  771.      * @param string $query query to be prepared
  772.      *
  773.      * @return mixed DB statement resource on success. DB_Error on failure.
  774.      *
  775.      * @see DB_common::execute()
  776.      * @access public
  777.      */
  778.     function prepare($query)
  779.     {
  780.         $tokens   preg_split('/((?<!\\\)[&?!])/'$query-1,
  781.                                PREG_SPLIT_DELIM_CAPTURE);
  782.         $token     = 0;
  783.         $types     = array();
  784.         $newtokens = array();
  785.  
  786.         foreach ($tokens as $val{
  787.             switch ($val{
  788.                 case '?':
  789.                     $types[$token++DB_PARAM_SCALAR;
  790.                     break;
  791.                 case '&':
  792.                     $types[$token++DB_PARAM_OPAQUE;
  793.                     break;
  794.                 case '!':
  795.                     $types[$token++DB_PARAM_MISC;
  796.                     break;
  797.                 default:
  798.                     $newtokens[preg_replace('/\\\([&?!])/'"\\1"$val);
  799.             }
  800.         }
  801.  
  802.         $this->prepare_tokens[&$newtokens;
  803.         end($this->prepare_tokens);
  804.  
  805.         $k key($this->prepare_tokens);
  806.         $this->prepare_types[$k$types;
  807.         $this->prepared_queries[$kimplode(' '$newtokens);
  808.  
  809.         return $k;
  810.     }
  811.  
  812.     // }}}
  813.     // {{{ autoPrepare()
  814.  
  815.     /**
  816.      * Automaticaly generate an insert or update query and pass it to prepare()
  817.      *
  818.      * @param string $table name of the table
  819.      * @param array $table_fields ordered array containing the fields names
  820.      * @param int $mode type of query to make (DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE)
  821.      * @param string $where in case of update queries, this string will be put after the sql WHERE statement
  822.      * @return resource handle for the query
  823.      * @see DB_common::prepare(), DB_common::buildManipSQL()
  824.      * @access public
  825.      */
  826.     function autoPrepare($table$table_fields$mode = DB_AUTOQUERY_INSERT$where = false)
  827.     {
  828.         $query $this->buildManipSQL($table$table_fields$mode$where);
  829.         return $this->prepare($query);
  830.     }
  831.  
  832.     // }}}
  833.     // {{{ autoExecute()
  834.  
  835.     /**
  836.      * Automaticaly generate an insert or update query and call prepare()
  837.      * and execute() with it
  838.      *
  839.      * @param string $table name of the table
  840.      * @param array $fields_values assoc ($key=>$value) where $key is a field name and $value its value
  841.      * @param int $mode type of query to make (DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE)
  842.      * @param string $where in case of update queries, this string will be put after the sql WHERE statement
  843.      * @return mixed  a new DB_Result or a DB_Error when fail
  844.      * @see DB_common::autoPrepare(), DB_common::buildManipSQL()
  845.      * @access public
  846.      */
  847.     function autoExecute($table$fields_values$mode = DB_AUTOQUERY_INSERT$where = false)
  848.     {
  849.         $sth $this->autoPrepare($tablearray_keys($fields_values)$mode$where);
  850.         $ret =$this->execute($stharray_values($fields_values));
  851.         $this->freePrepared($sth);
  852.         return $ret;
  853.  
  854.     }
  855.  
  856.     // }}}
  857.     // {{{ buildManipSQL()
  858.  
  859.     /**
  860.      * Make automaticaly an sql query for prepare()
  861.      *
  862.      * Example : buildManipSQL('table_sql', array('field1', 'field2', 'field3'), DB_AUTOQUERY_INSERT)
  863.      *           will return the string : INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?)
  864.      * NB : - This belongs more to a SQL Builder class, but this is a simple facility
  865.      *      - Be carefull ! If you don't give a $where param with an UPDATE query, all
  866.      *        the records of the table will be updated !
  867.      *
  868.      * @param string $table name of the table
  869.      * @param array $table_fields ordered array containing the fields names
  870.      * @param int $mode type of query to make (DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE)
  871.      * @param string $where in case of update queries, this string will be put after the sql WHERE statement
  872.      * @return string sql query for prepare()
  873.      * @access public
  874.      */
  875.     function buildManipSQL($table$table_fields$mode$where = false)
  876.     {
  877.         if (count($table_fields== 0{
  878.             $this->raiseError(DB_ERROR_NEED_MORE_DATA);
  879.         }
  880.         $first = true;
  881.         switch ($mode{
  882.             case DB_AUTOQUERY_INSERT:
  883.                 $values '';
  884.                 $names '';
  885.                 foreach ($table_fields as $value{
  886.                     if ($first{
  887.                         $first = false;
  888.                     else {
  889.                         $names .= ',';
  890.                         $values .= ',';
  891.                     }
  892.                     $names .= $value;
  893.                     $values .= '?';
  894.                 }
  895.                 return "INSERT INTO $table ($names) VALUES ($values)";
  896.             case DB_AUTOQUERY_UPDATE:
  897.                 $set '';
  898.                 foreach ($table_fields as $value{
  899.                     if ($first{
  900.                         $first = false;
  901.                     else {
  902.                         $set .= ',';
  903.                     }
  904.                     $set .= "$value = ?";
  905.                 }
  906.                 $sql = "UPDATE $table SET $set";
  907.                 if ($where{
  908.                     $sql .= " WHERE $where";
  909.                 }
  910.                 return $sql;
  911.             default:
  912.                 $this->raiseError(DB_ERROR_SYNTAX);
  913.         }
  914.     }
  915.  
  916.     // }}}
  917.     // {{{ execute()
  918.  
  919.     /**
  920.      * Executes a DB statement prepared with prepare()
  921.      *
  922.      * Example 1.
  923.      * <code> <?php
  924.      * $sth = $dbh->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)');
  925.      * $data = array(
  926.      *     "John's text",
  927.      *     "'it''s good'",
  928.      *     'filename.txt'
  929.      * );
  930.      * $res =& $dbh->execute($sth, $data);
  931.      * ?></code>
  932.      *
  933.      * @param resource  $stmt  a DB statement resource returned from prepare()
  934.      * @param mixed  $data  array, string or numeric data to be used in
  935.      *                       execution of the statement.  Quantity of items
  936.      *                       passed must match quantity of placeholders in
  937.      *                       query:  meaning 1 placeholder for non-array
  938.      *                       parameters or 1 placeholder per array element.
  939.      *
  940.      * @return object  new DB_Result or a DB_Error when fail
  941.      *
  942.      *  {@internal ibase and oci8 have their own execute() methods.}}
  943.      *
  944.      * @see DB_common::prepare()
  945.      * @access public
  946.      */
  947.     function &execute($stmt$data = array())
  948.     {
  949.         $realquery $this->executeEmulateQuery($stmt$data);
  950.         if (DB::isError($realquery)) {
  951.             return $realquery;
  952.         }
  953.         $result $this->simpleQuery($realquery);
  954.  
  955.         if (DB::isError($result|| $result === DB_OK{
  956.             return $result;
  957.         else {
  958.             $tmp =new DB_result($this$result);
  959.             return $tmp;
  960.         }
  961.     }
  962.  
  963.     // }}}
  964.     // {{{ executeEmulateQuery()
  965.  
  966.     /**
  967.      * Emulates the execute statement, when not supported
  968.      *
  969.      * @param resource  $stmt  a DB statement resource returned from execute()
  970.      * @param mixed  $data  array, string or numeric data to be used in
  971.      *                       execution of the statement.  Quantity of items
  972.      *                       passed must match quantity of placeholders in
  973.      *                       query:  meaning 1 placeholder for non-array
  974.      *                       parameters or 1 placeholder per array element.
  975.      *
  976.      * @return mixed a string containing the real query run when emulating
  977.      *                prepare/execute.  A DB error code is returned on failure.
  978.      *
  979.      * @see DB_common::execute()
  980.      * @access private
  981.      */
  982.     function executeEmulateQuery($stmt$data = array())
  983.     {
  984.         if (!is_array($data)) {
  985.             $data = array($data);
  986.         }
  987.  
  988.         if (count($this->prepare_types[$stmt]!= count($data)) {
  989.             $this->last_query = $this->prepared_queries[$stmt];
  990.             return $this->raiseError(DB_ERROR_MISMATCH);
  991.         }
  992.  
  993.         $realquery $this->prepare_tokens[$stmt][0];
  994.  
  995.         $i = 0;
  996.         foreach ($data as $value{
  997.             if ($this->prepare_types[$stmt][$i== DB_PARAM_SCALAR{
  998.                 $realquery .= $this->quoteSmart($value);
  999.             elseif ($this->prepare_types[$stmt][$i== DB_PARAM_OPAQUE{
  1000.                 $fp @fopen($value'rb');
  1001.                 if (!$fp{
  1002.                     return $this->raiseError(DB_ERROR_ACCESS_VIOLATION);
  1003.                 }
  1004.                 $realquery .= $this->quoteSmart(fread($fpfilesize($value)));
  1005.                 fclose($fp);
  1006.             else {
  1007.                 $realquery .= $value;
  1008.             }
  1009.  
  1010.             $realquery .= $this->prepare_tokens[$stmt][++$i];
  1011.         }
  1012.  
  1013.         return $realquery;
  1014.     }
  1015.  
  1016.     // }}}
  1017.     // {{{ executeMultiple()
  1018.  
  1019.     /**
  1020.      * This function does several execute() calls on the same
  1021.      * statement handle
  1022.      *
  1023.      * $data must be an array indexed numerically
  1024.      * from 0, one execute call is done for every "row" in the array.
  1025.      *
  1026.      * If an error occurs during execute(), executeMultiple() does not
  1027.      * execute the unfinished rows, but rather returns that error.
  1028.      *
  1029.      * @param resource $stmt query handle from prepare()
  1030.      * @param array    $data numeric array containing the
  1031.      *                        data to insert into the query
  1032.      *
  1033.      * @return mixed DB_OK or DB_Error
  1034.      *
  1035.      * @see DB_common::prepare(), DB_common::execute()
  1036.      * @access public
  1037.      */
  1038.     function executeMultiple($stmt$data)
  1039.     {
  1040.         foreach ($data as $value{
  1041.             $res =$this->execute($stmt$value);
  1042.             if (DB::isError($res)) {
  1043.                 return $res;
  1044.             }
  1045.         }
  1046.         return DB_OK;
  1047.     }
  1048.  
  1049.     // }}}
  1050.     // {{{ freePrepared()
  1051.  
  1052.     /**
  1053.      * Free the resource used in a prepared query
  1054.      *
  1055.      * @param $stmt The resurce returned by the prepare() function
  1056.      * @see DB_common::prepare()
  1057.      */
  1058.     function freePrepared($stmt)
  1059.     {
  1060.         // Free the internal prepared vars
  1061.         if (isset($this->prepare_tokens[$stmt])) {
  1062.             unset($this->prepare_tokens[$stmt]);
  1063.             unset($this->prepare_types[$stmt]);
  1064.             unset($this->prepared_queries[$stmt]);
  1065.             return true;
  1066.         }
  1067.         return false;
  1068.     }
  1069.  
  1070.     // }}}
  1071.     // {{{ modifyQuery()
  1072.  
  1073.     /**
  1074.      * This method is used by backends to alter queries for various
  1075.      * reasons
  1076.      *
  1077.      * It is defined here to assure that all implementations
  1078.      * have this method defined.
  1079.      *
  1080.      * @param string $query  query to modify
  1081.      *
  1082.      * @return the new (modified) query
  1083.      *
  1084.      * @access private
  1085.      */
  1086.     function modifyQuery($query{
  1087.         return $query;
  1088.     }
  1089.  
  1090.     // }}}
  1091.     // {{{ modifyLimitQuery()
  1092.  
  1093.     /**
  1094.      * This method is used by backends to alter limited queries
  1095.      *
  1096.      * @param string  $query query to modify
  1097.      * @param integer $from  the row to start to fetching
  1098.      * @param integer $count the numbers of rows to fetch
  1099.      *
  1100.      * @return the new (modified) query
  1101.      *
  1102.      * @access private
  1103.      */
  1104.     function modifyLimitQuery($query$from$count$params = array())
  1105.     {
  1106.         return $query;
  1107.     }
  1108.  
  1109.     // }}}
  1110.     // {{{ query()
  1111.  
  1112.     /**
  1113.      * Send a query to the database and return any results with a
  1114.      * DB_result object
  1115.      *
  1116.      * The query string can be either a normal statement to be sent directly
  1117.      * to the server OR if <var>$params</var> are passed the query can have
  1118.      * placeholders and it will be passed through prepare() and execute().
  1119.      *
  1120.      * @param string $query  the SQL query or the statement to prepare
  1121.      * @param mixed  $params array, string or numeric data to be used in
  1122.      *                        execution of the statement.  Quantity of items
  1123.      *                        passed must match quantity of placeholders in
  1124.      *                        query:  meaning 1 placeholder for non-array
  1125.      *                        parameters or 1 placeholder per array element.
  1126.      *
  1127.      * @return mixed  a DB_result object or DB_OK on success, a DB
  1128.      *                 error on failure
  1129.      *
  1130.      * @see DB_result, DB_common::prepare(), DB_common::execute()
  1131.      * @access public
  1132.      */
  1133.     function &query($query$params = array())
  1134.     {
  1135.         if (sizeof($params> 0{
  1136.             $sth $this->prepare($query);
  1137.             if (DB::isError($sth)) {
  1138.                 return $sth;
  1139.             }
  1140.             $ret =$this->execute($sth$params);
  1141.             $this->freePrepared($sth);
  1142.             return $ret;
  1143.         else {
  1144.             $result $this->simpleQuery($query);
  1145.             if (DB::isError($result|| $result === DB_OK{
  1146.                 return $result;
  1147.             else {
  1148.                 $tmp =new DB_result($this$result);
  1149.                 return $tmp;
  1150.             }
  1151.         }
  1152.     }
  1153.  
  1154.     // }}}
  1155.     // {{{ limitQuery()
  1156.  
  1157.     /**
  1158.      * Generates a limited query
  1159.      *
  1160.      * @param string  $query query
  1161.      * @param integer $from  the row to start to fetching
  1162.      * @param integer $count the numbers of rows to fetch
  1163.      * @param array   $params required for a statement
  1164.      *
  1165.      * @return mixed a DB_Result object, DB_OK or a DB_Error
  1166.      *
  1167.      * @access public
  1168.      */
  1169.     function &limitQuery($query$from$count$params = array())
  1170.     {
  1171.         $query $this->modifyLimitQuery($query$from$count$params);
  1172.         if (DB::isError($query)){
  1173.             return $query;
  1174.         }
  1175.         $result =$this->query($query$params);
  1176.         if (is_a($result'DB_result')) {
  1177.             $result->setOption('limit_from'$from);
  1178.             $result->setOption('limit_count'$count);
  1179.         }
  1180.         return $result;
  1181.     }
  1182.  
  1183.     // }}}
  1184.     // {{{ getOne()
  1185.  
  1186.     /**
  1187.      * Fetch the first column of the first row of data returned from
  1188.      * a query
  1189.      *
  1190.      * Takes care of doing the query and freeing the results when finished.
  1191.      *
  1192.      * @param string $query  the SQL query
  1193.      * @param mixed  $params array, string or numeric data to be used in
  1194.      *                        execution of the statement.  Quantity of items
  1195.      *                        passed must match quantity of placeholders in
  1196.      *                        query:  meaning 1 placeholder for non-array
  1197.      *                        parameters or 1 placeholder per array element.
  1198.      *
  1199.      * @return mixed  the returned value of the query.  DB_Error on failure.
  1200.      *
  1201.      * @access public
  1202.      */
  1203.     function &getOne($query$params = array())
  1204.     {
  1205.         settype($params'array');
  1206.         if (sizeof($params> 0{
  1207.             $sth $this->prepare($query);
  1208.             if (DB::isError($sth)) {
  1209.                 return $sth;
  1210.             }
  1211.             $res =$this->execute($sth$params);
  1212.             $this->freePrepared($sth);
  1213.         else {
  1214.             $res =$this->query($query);
  1215.         }
  1216.  
  1217.         if (DB::isError($res)) {
  1218.             return $res;
  1219.         }
  1220.  
  1221.         $err $res->fetchInto($rowDB_FETCHMODE_ORDERED);
  1222.         $res->free();
  1223.  
  1224.         if ($err !== DB_OK{
  1225.             return $err;
  1226.         }
  1227.  
  1228.         return $row[0];
  1229.     }
  1230.  
  1231.     // }}}
  1232.     // {{{ getRow()
  1233.  
  1234.     /**
  1235.      * Fetch the first row of data returned from a query
  1236.      *
  1237.      * Takes care of doing the query and freeing the results when finished.
  1238.      *
  1239.      * @param string $query  the SQL query
  1240.      * @param array  $params array to be used in execution of the statement.
  1241.      *                        Quantity of array elements must match quantity
  1242.      *                        of placeholders in query.  This function does
  1243.      *                        NOT support scalars.
  1244.      * @param int    $fetchmode  the fetch mode to use
  1245.      *
  1246.      * @return array the first row of results as an array indexed from
  1247.      *                0, or a DB error code.
  1248.      *
  1249.      * @access public
  1250.      */
  1251.     function &getRow($query,
  1252.                      $params = array(),
  1253.                      $fetchmode = DB_FETCHMODE_DEFAULT)
  1254.     {
  1255.         // compat check, the params and fetchmode parameters used to
  1256.         // have the opposite order
  1257.         if (!is_array($params)) {
  1258.             if (is_array($fetchmode)) {
  1259.                 if ($params === null{
  1260.                     $tmp DB_FETCHMODE_DEFAULT;
  1261.                 else {
  1262.                     $tmp $params;
  1263.                 }
  1264.                 $params $fetchmode;
  1265.                 $fetchmode $tmp;
  1266.             elseif ($params !== null{
  1267.                 $fetchmode $params;
  1268.                 $params = array();
  1269.             }
  1270.         }
  1271.  
  1272.         if (sizeof($params> 0{
  1273.             $sth $this->prepare($query);
  1274.             if (DB::isError($sth)) {
  1275.                 return $sth;
  1276.             }
  1277.             $res =$this->execute($sth$params);
  1278.             $this->freePrepared($sth);
  1279.         else {
  1280.             $res =$this->query($query);
  1281.         }
  1282.  
  1283.         if (DB::isError($res)) {
  1284.             return $res;
  1285.         }
  1286.  
  1287.         $err $res->fetchInto($row$fetchmode);
  1288.  
  1289.         $res->free();
  1290.  
  1291.         if ($err !== DB_OK{
  1292.             return $err;
  1293.         }
  1294.  
  1295.         return $row;
  1296.     }
  1297.  
  1298.     // }}}
  1299.     // {{{ getCol()
  1300.  
  1301.     /**
  1302.      * Fetch a single column from a result set and return it as an
  1303.      * indexed array
  1304.      *
  1305.      * @param string $query  the SQL query
  1306.      * @param mixed  $col    which column to return (integer [column number,
  1307.      *                        starting at 0] or string [column name])
  1308.      * @param mixed  $params array, string or numeric data to be used in
  1309.      *                        execution of the statement.  Quantity of items
  1310.      *                        passed must match quantity of placeholders in
  1311.      *                        query:  meaning 1 placeholder for non-array
  1312.      *                        parameters or 1 placeholder per array element.
  1313.      *
  1314.      * @return array  an indexed array with the data from the first
  1315.      *                 row at index 0, or a DB error code
  1316.      *
  1317.      * @see DB_common::query()
  1318.      * @access public
  1319.      */
  1320.     function &getCol($query$col = 0$params = array())
  1321.     {
  1322.         settype($params'array');
  1323.         if (sizeof($params> 0{
  1324.             $sth $this->prepare($query);
  1325.  
  1326.             if (DB::isError($sth)) {
  1327.                 return $sth;
  1328.             }
  1329.  
  1330.             $res =$this->execute($sth$params);
  1331.             $this->freePrepared($sth);
  1332.         else {
  1333.             $res =$this->query($query);
  1334.         }
  1335.  
  1336.         if (DB::isError($res)) {
  1337.             return $res;
  1338.         }
  1339.  
  1340.         $fetchmode is_int($colDB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC;
  1341.         $ret = array();
  1342.  
  1343.         while (is_array($row $res->fetchRow($fetchmode))) {
  1344.             $ret[$row[$col];
  1345.         }
  1346.  
  1347.         $res->free();
  1348.  
  1349.         if (DB::isError($row)) {
  1350.             $ret $row;
  1351.         }
  1352.  
  1353.         return $ret;
  1354.     }
  1355.  
  1356.     // }}}
  1357.     // {{{ getAssoc()
  1358.  
  1359.     /**
  1360.      * Fetch the entire result set of a query and return it as an
  1361.      * associative array using the first column as the key
  1362.      *
  1363.      * If the result set contains more than two columns, the value
  1364.      * will be an array of the values from column 2-n.  If the result
  1365.      * set contains only two columns, the returned value will be a
  1366.      * scalar with the value of the second column (unless forced to an
  1367.      * array with the $force_array parameter).  A DB error code is
  1368.      * returned on errors.  If the result set contains fewer than two
  1369.      * columns, a DB_ERROR_TRUNCATED error is returned.
  1370.      *
  1371.      * For example, if the table "mytable" contains:
  1372.      *
  1373.      * <pre>
  1374.      *  ID      TEXT       DATE
  1375.      * --------------------------------
  1376.      *  1       'one'      944679408
  1377.      *  2       'two'      944679408
  1378.      *  3       'three'    944679408
  1379.      * </pre>
  1380.      *
  1381.      * Then the call getAssoc('SELECT id,text FROM mytable') returns:
  1382.      * <pre>
  1383.      *   array(
  1384.      *     '1' => 'one',
  1385.      *     '2' => 'two',
  1386.      *     '3' => 'three',
  1387.      *   )
  1388.      * </pre>
  1389.      *
  1390.      * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
  1391.      * <pre>
  1392.      *   array(
  1393.      *     '1' => array('one', '944679408'),
  1394.      *     '2' => array('two', '944679408'),
  1395.      *     '3' => array('three', '944679408')
  1396.      *   )
  1397.      * </pre>
  1398.      *
  1399.      * If the more than one row occurs with the same value in the
  1400.      * first column, the last row overwrites all previous ones by
  1401.      * default.  Use the $group parameter if you don't want to
  1402.      * overwrite like this.  Example:
  1403.      *
  1404.      * <pre>
  1405.      * getAssoc('SELECT category,id,name FROM mytable', false, null,
  1406.      *          DB_FETCHMODE_ASSOC, true) returns:
  1407.      *
  1408.      *   array(
  1409.      *     '1' => array(array('id' => '4', 'name' => 'number four'),
  1410.      *                  array('id' => '6', 'name' => 'number six')
  1411.      *            ),
  1412.      *     '9' => array(array('id' => '4', 'name' => 'number four'),
  1413.      *                  array('id' => '6', 'name' => 'number six')
  1414.      *            )
  1415.      *   )
  1416.      * </pre>
  1417.      *
  1418.      * Keep in mind that database functions in PHP usually return string
  1419.      * values for results regardless of the database's internal type.
  1420.      *
  1421.      * @param string  $query  the SQL query
  1422.      * @param boolean $force_array  used only when the query returns
  1423.      *                               exactly two columns.  If true, the values
  1424.      *                               of the returned array will be one-element
  1425.      *                               arrays instead of scalars.
  1426.      * @param mixed   $params array, string or numeric data to be used in
  1427.      *                         execution of the statement.  Quantity of items
  1428.      *                         passed must match quantity of placeholders in
  1429.      *                         query:  meaning 1 placeholder for non-array
  1430.      *                         parameters or 1 placeholder per array element.
  1431.      * @param boolean $group  if true, the values of the returned array
  1432.      *                         is wrapped in another array.  If the same
  1433.      *                         key value (in the first column) repeats
  1434.      *                         itself, the values will be appended to
  1435.      *                         this array instead of overwriting the
  1436.      *                         existing values.
  1437.      *
  1438.      * @return array  associative array with results from the query.
  1439.      *                 DB Error on failure.
  1440.      *
  1441.      * @access public
  1442.      */
  1443.     function &getAssoc($query$force_array = false$params = array(),
  1444.                        $fetchmode = DB_FETCHMODE_DEFAULT$group = false)
  1445.     {
  1446.         settype($params'array');
  1447.         if (sizeof($params> 0{
  1448.             $sth $this->prepare($query);
  1449.  
  1450.             if (DB::isError($sth)) {
  1451.                 return $sth;
  1452.             }
  1453.  
  1454.             $res =$this->execute($sth$params);
  1455.             $this->freePrepared($sth);
  1456.         else {
  1457.             $res =$this->query($query);
  1458.         }
  1459.  
  1460.         if (DB::isError($res)) {
  1461.             return $res;
  1462.         }
  1463.         if ($fetchmode == DB_FETCHMODE_DEFAULT{
  1464.             $fetchmode $this->fetchmode;
  1465.         }
  1466.         $cols $res->numCols();
  1467.  
  1468.         if ($cols < 2{
  1469.             $tmp =$this->raiseError(DB_ERROR_TRUNCATED);
  1470.             return $tmp;
  1471.         }
  1472.  
  1473.         $results = array();
  1474.  
  1475.         if ($cols > 2 || $force_array{
  1476.             // return array values
  1477.             // XXX this part can be optimized
  1478.             if ($fetchmode == DB_FETCHMODE_ASSOC{
  1479.                 while (is_array($row $res->fetchRow(DB_FETCHMODE_ASSOC))) {
  1480.                     reset($row);
  1481.                     $key current($row);
  1482.                     unset($row[key($row)]);
  1483.                     if ($group{
  1484.                         $results[$key][$row;
  1485.                     else {
  1486.                         $results[$key$row;
  1487.                     }
  1488.                 }
  1489.             elseif ($fetchmode == DB_FETCHMODE_OBJECT{
  1490.                 while ($row $res->fetchRow(DB_FETCHMODE_OBJECT)) {
  1491.                     $arr get_object_vars($row);
  1492.                     $key current($arr);
  1493.                     if ($group{
  1494.                         $results[$key][$row;
  1495.                     else {
  1496.                         $results[$key$row;
  1497.                     }
  1498.                 }
  1499.             else {
  1500.                 while (is_array($row $res->fetchRow(DB_FETCHMODE_ORDERED))) {
  1501.                     // we shift away the first element to get
  1502.                     // indices running from 0 again
  1503.                     $key array_shift($row);
  1504.                     if ($group{
  1505.                         $results[$key][$row;
  1506.                     else {
  1507.                         $results[$key$row;
  1508.                     }
  1509.                 }
  1510.             }
  1511.             if (DB::isError($row)) {
  1512.                 $results $row;
  1513.             }
  1514.         else {
  1515.             // return scalar values
  1516.             while (is_array($row $res->fetchRow(DB_FETCHMODE_ORDERED))) {
  1517.                 if ($group{
  1518.                     $results[$row[0]][$row[1];
  1519.                 else {
  1520.                     $results[$row[0]] $row[1];
  1521.                 }
  1522.             }
  1523.             if (DB::isError($row)) {
  1524.                 $results $row;
  1525.             }
  1526.         }
  1527.  
  1528.         $res->free();
  1529.  
  1530.         return $results;
  1531.     }
  1532.  
  1533.     // }}}
  1534.     // {{{ getAll()
  1535.  
  1536.     /**
  1537.      * Fetch all the rows returned from a query
  1538.      *
  1539.      * @param string $query  the SQL query
  1540.      * @param array  $params array to be used in execution of the statement.
  1541.      *                        Quantity of array elements must match quantity
  1542.      *                        of placeholders in query.  This function does
  1543.      *                        NOT support scalars.
  1544.      * @param int    $fetchmode  the fetch mode to use
  1545.      *
  1546.      * @return array  an nested array.  DB error on failure.
  1547.      *
  1548.      * @access public
  1549.      */
  1550.     function &getAll($query,
  1551.                      $params = array(),
  1552.                      $fetchmode = DB_FETCHMODE_DEFAULT)
  1553.     {
  1554.         // compat check, the params and fetchmode parameters used to
  1555.         // have the opposite order
  1556.         if (!is_array($params)) {
  1557.             if (is_array($fetchmode)) {
  1558.                 if ($params === null{
  1559.                     $tmp DB_FETCHMODE_DEFAULT;
  1560.                 else {
  1561.                     $tmp $params;
  1562.                 }
  1563.                 $params $fetchmode;
  1564.                 $fetchmode $tmp;
  1565.             elseif ($params !== null{
  1566.                 $fetchmode $params;
  1567.                 $params = array();
  1568.             }
  1569.         }
  1570.  
  1571.         if (sizeof($params> 0{
  1572.             $sth $this->prepare($query);
  1573.  
  1574.             if (DB::isError($sth)) {
  1575.                 return $sth;
  1576.             }
  1577.  
  1578.             $res =$this->execute($sth$params);
  1579.             $this->freePrepared($sth);
  1580.         else {
  1581.             $res =$this->query($query);
  1582.         }
  1583.  
  1584.         if (DB::isError($res|| $res === DB_OK{
  1585.             return $res;
  1586.         }
  1587.  
  1588.         $results = array();
  1589.         while (DB_OK === $res->fetchInto($row$fetchmode)) {
  1590.             if ($fetchmode DB_FETCHMODE_FLIPPED{
  1591.                 foreach ($row as $key => $val{
  1592.                     $results[$key][$val;
  1593.                 }
  1594.             else {
  1595.                 $results[$row;
  1596.             }
  1597.         }
  1598.  
  1599.         $res->free();
  1600.  
  1601.         if (DB::isError($row)) {
  1602.             $tmp =$this->raiseError($row);
  1603.             return $tmp;
  1604.         }
  1605.         return $results;
  1606.     }
  1607.  
  1608.     // }}}
  1609.     // {{{ autoCommit()
  1610.  
  1611.     /**
  1612.      * enable automatic Commit
  1613.      *
  1614.      * @param boolean $onoff 
  1615.      * @return mixed DB_Error
  1616.      *
  1617.      * @access public
  1618.      */
  1619.     function autoCommit($onoff=false)
  1620.     {
  1621.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1622.     }
  1623.  
  1624.     // }}}
  1625.     // {{{ commit()
  1626.  
  1627.     /**
  1628.      * starts a Commit
  1629.      *
  1630.      * @return mixed DB_Error
  1631.      *
  1632.      * @access public
  1633.      */
  1634.     function commit()
  1635.     {
  1636.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1637.     }
  1638.  
  1639.     // }}}
  1640.     // {{{ rollback()
  1641.  
  1642.     /**
  1643.      * starts a rollback
  1644.      *
  1645.      * @return mixed DB_Error
  1646.      *
  1647.      * @access public
  1648.      */
  1649.     function rollback()
  1650.     {
  1651.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1652.     }
  1653.  
  1654.     // }}}
  1655.     // {{{ numRows()
  1656.  
  1657.     /**
  1658.      * Returns the number of rows in a result object
  1659.      *
  1660.      * @param object DB_Result the result object to check
  1661.      *
  1662.      * @return mixed DB_Error or the number of rows
  1663.      *
  1664.      * @access public
  1665.      */
  1666.     function numRows($result)
  1667.     {
  1668.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1669.     }
  1670.  
  1671.     // }}}
  1672.     // {{{ affectedRows()
  1673.  
  1674.     /**
  1675.      * Returns the affected rows of a query
  1676.      *
  1677.      * @return mixed DB_Error or number of rows
  1678.      *
  1679.      * @access public
  1680.      */
  1681.     function affectedRows()
  1682.     {
  1683.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1684.     }
  1685.  
  1686.     // }}}
  1687.     // {{{ errorNative()
  1688.  
  1689.     /**
  1690.      * Returns an errormessage, provides by the database
  1691.      *
  1692.      * @return mixed DB_Error or message
  1693.      *
  1694.      * @access public
  1695.      */
  1696.     function errorNative()
  1697.     {
  1698.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1699.     }
  1700.  
  1701.     // }}}
  1702.     // {{{ getSequenceName()
  1703.  
  1704.     /**
  1705.      * Generate the name used inside the database for a sequence
  1706.      *
  1707.      * The createSequence() docblock contains notes about storing sequence
  1708.      * names.
  1709.      *
  1710.      * @param string $sqn  the sequence's public name
  1711.      *
  1712.      * @return string  the sequence's name in the backend
  1713.      *
  1714.      * @see DB_common::createSequence(), DB_common::dropSequence(),
  1715.      *       DB_common::nextID(), DB_common::setOption()
  1716.      * @access private
  1717.      */
  1718.     function getSequenceName($sqn)
  1719.     {
  1720.         return sprintf($this->getOption('seqname_format'),
  1721.                        preg_replace('/[^a-z0-9_.]/i''_'$sqn));
  1722.     }
  1723.  
  1724.     // }}}
  1725.     // {{{ nextId()
  1726.  
  1727.     /**
  1728.      * Returns the next free id in a sequence
  1729.      *
  1730.      * @param string  $seq_name  name of the sequence
  1731.      * @param boolean $ondemand  when true, the seqence is automatically
  1732.      *                            created if it does not exist
  1733.      *
  1734.      * @return int  the next id number in the sequence.  DB_Error if problem.
  1735.      *
  1736.      * @see DB_common::createSequence(), DB_common::dropSequence(),
  1737.      *       DB_common::getSequenceName()
  1738.      * @access public
  1739.      */
  1740.     function nextId($seq_name$ondemand = true)
  1741.     {
  1742.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1743.     }
  1744.  
  1745.     // }}}
  1746.     // {{{ createSequence()
  1747.  
  1748.     /**
  1749.      * Creates a new sequence
  1750.      *
  1751.      * The name of a given sequence is determined by passing the string
  1752.      * provided in the <var>$seq_name</var> argument through PHP's sprintf()
  1753.      * function using the value from the <var>seqname_format</var> option as
  1754.      * the sprintf()'s format argument.
  1755.      *
  1756.      * <var>seqname_format</var> is set via setOption().
  1757.      *
  1758.      * @param string $seq_name  name of the new sequence
  1759.      *
  1760.      * @return int  DB_OK on success.  A DB_Error object is returned if
  1761.      *               problems arise.
  1762.      *
  1763.      * @see DB_common::dropSequence(), DB_common::getSequenceName(),
  1764.      *       DB_common::nextID()
  1765.      * @access public
  1766.      */
  1767.     function createSequence($seq_name)
  1768.     {
  1769.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1770.     }
  1771.  
  1772.     // }}}
  1773.     // {{{ dropSequence()
  1774.  
  1775.     /**
  1776.      * Deletes a sequence
  1777.      *
  1778.      * @param string $seq_name  name of the sequence to be deleted
  1779.      *
  1780.      * @return int  DB_OK on success.  DB_Error if problems.
  1781.      *
  1782.      * @see DB_common::createSequence(), DB_common::getSequenceName(),
  1783.      *       DB_common::nextID()
  1784.      * @access public
  1785.      */
  1786.     function dropSequence($seq_name)
  1787.     {
  1788.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1789.     }
  1790.  
  1791.     // }}}
  1792.     // {{{ tableInfo()
  1793.  
  1794.     /**
  1795.      * Returns information about a table or a result set
  1796.      *
  1797.      * The format of the resulting array depends on which <var>$mode</var>
  1798.      * you select.  The sample output below is based on this query:
  1799.      * <pre>
  1800.      *    SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
  1801.      *    FROM tblFoo
  1802.      *    JOIN tblBar ON tblFoo.fldId = tblBar.fldId
  1803.      * </pre>
  1804.      *
  1805.      * <ul>
  1806.      * <li>
  1807.      *
  1808.      * <kbd>null</kbd> (default)
  1809.      *   <pre>
  1810.      *   [0] => Array (
  1811.      *       [table] => tblFoo
  1812.      *       [name] => fldId
  1813.      *       [type] => int
  1814.      *       [len] => 11
  1815.      *       [flags] => primary_key not_null
  1816.      *   )
  1817.      *   [1] => Array (
  1818.      *       [table] => tblFoo
  1819.      *       [name] => fldPhone
  1820.      *       [type] => string
  1821.      *       [len] => 20
  1822.      *       [flags] =>
  1823.      *   )
  1824.      *   [2] => Array (
  1825.      *       [table] => tblBar
  1826.      *       [name] => fldId
  1827.      *       [type] => int
  1828.      *       [len] => 11
  1829.      *       [flags] => primary_key not_null
  1830.      *   )
  1831.      *   </pre>
  1832.      *
  1833.      * </li><li>
  1834.      *
  1835.      * <kbd>DB_TABLEINFO_ORDER</kbd>
  1836.      *
  1837.      *   <p>In addition to the information found in the default output,
  1838.      *   a notation of the number of columns is provided by the
  1839.      *   <samp>num_fields</samp> element while the <samp>order</samp>
  1840.      *   element provides an array with the column names as the keys and
  1841.      *   their location index number (corresponding to the keys in the
  1842.      *   the default output) as the values.</p>
  1843.      *
  1844.      *   <p>If a result set has identical field names, the last one is
  1845.      *   used.</p>
  1846.      *
  1847.      *   <pre>
  1848.      *   [num_fields] => 3
  1849.      *   [order] => Array (
  1850.      *       [fldId] => 2
  1851.      *       [fldTrans] => 1
  1852.      *   )
  1853.      *   </pre>
  1854.      *
  1855.      * </li><li>
  1856.      *
  1857.      * <kbd>DB_TABLEINFO_ORDERTABLE</kbd>
  1858.      *
  1859.      *   <p>Similar to <kbd>DB_TABLEINFO_ORDER</kbd> but adds more
  1860.      *   dimensions to the array in which the table names are keys and
  1861.      *   the field names are sub-keys.  This is helpful for queries that
  1862.      *   join tables which have identical field names.</p>
  1863.      *
  1864.      *   <pre>
  1865.      *   [num_fields] => 3
  1866.      *   [ordertable] => Array (
  1867.      *       [tblFoo] => Array (
  1868.      *           [fldId] => 0
  1869.      *           [fldPhone] => 1
  1870.      *       )
  1871.      *       [tblBar] => Array (
  1872.      *           [fldId] => 2
  1873.      *       )
  1874.      *   )
  1875.      *   </pre>
  1876.      *
  1877.      * </li>
  1878.      * </ul>
  1879.      *
  1880.      * The <samp>flags</samp> element contains a space separated list
  1881.      * of extra information about the field.  This data is inconsistent
  1882.      * between DBMS's due to the way each DBMS works.
  1883.      *   + <samp>primary_key</samp>
  1884.      *   + <samp>unique_key</samp>
  1885.      *   + <samp>multiple_key</samp>
  1886.      *   + <samp>not_null</samp>
  1887.      *
  1888.      * Most DBMS's only provide the <samp>table</samp> and <samp>flags</samp>
  1889.      * elements if <var>$result</var> is a table name.  The following DBMS's
  1890.      * provide full information from queries:
  1891.      *   + fbsql
  1892.      *   + mysql
  1893.      *
  1894.      * If the 'portability' option has <samp>DB_PORTABILITY_LOWERCASE</samp>
  1895.      * turned on, the names of tables and fields will be lowercased.
  1896.      *
  1897.      * @param object|string $result  DB_result object from a query or a
  1898.      *                                 string containing the name of a table.
  1899.      *                                 While this also accepts a query result
  1900.      *                                 resource identifier, this behavior is
  1901.      *                                 deprecated.
  1902.      * @param int  $mode   either unused or one of the tableInfo modes:
  1903.      *                      <kbd>DB_TABLEINFO_ORDERTABLE</kbd>,
  1904.      *                      <kbd>DB_TABLEINFO_ORDER</kbd> or
  1905.      *                      <kbd>DB_TABLEINFO_FULL</kbd> (which does both).
  1906.      *                      These are bitwise, so the first two can be
  1907.      *                      combined using <kbd>|</kbd>.
  1908.      * @return array  an associative array with the information requested.
  1909.      *                 If something goes wrong an error object is returned.
  1910.      *
  1911.      * @see DB_common::setOption()
  1912.      * @access public
  1913.      */
  1914.     function tableInfo($result$mode = null)
  1915.     {
  1916.         /*
  1917.          * If the DB_<driver> class has a tableInfo() method, that one
  1918.          * overrides this one.  But, if the driver doesn't have one,
  1919.          * this method runs and tells users about that fact.
  1920.          */
  1921.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1922.     }
  1923.  
  1924.     // }}}
  1925.     // {{{ getTables()
  1926.  
  1927.     /**
  1928.      * @deprecated  Deprecated in release 1.2 or lower
  1929.      */
  1930.     function getTables()
  1931.     {
  1932.         return $this->getListOf('tables');
  1933.     }
  1934.  
  1935.     // }}}
  1936.     // {{{ getListOf()
  1937.  
  1938.     /**
  1939.      * list internal DB info
  1940.      * valid values for $type are db dependent,
  1941.      * often: databases, users, view, functions
  1942.      *
  1943.      * @param string $type type of requested info
  1944.      *
  1945.      * @return mixed DB_Error or the requested data
  1946.      *
  1947.      * @access public
  1948.      */
  1949.     function getListOf($type)
  1950.     {
  1951.         $sql $this->getSpecialQuery($type);
  1952.         if ($sql === null{                                // No support
  1953.             return $this->raiseError(DB_ERROR_UNSUPPORTED);
  1954.         elseif (is_int($sql|| DB::isError($sql)) {      // Previous error
  1955.             return $this->raiseError($sql);
  1956.         elseif (is_array($sql)) {                         // Already the result
  1957.             return $sql;
  1958.         }
  1959.         return $this->getCol($sql);                         // Launch this query
  1960.     }
  1961.  
  1962.     // }}}
  1963.     // {{{ getSpecialQuery()
  1964.  
  1965.     /**
  1966.      * Returns the query needed to get some backend info
  1967.      *
  1968.      * @param string $type What kind of info you want to retrieve
  1969.      *
  1970.      * @return string The SQL query string
  1971.      *
  1972.      * @access public
  1973.      */
  1974.     function getSpecialQuery($type)
  1975.     {
  1976.         return $this->raiseError(DB_ERROR_UNSUPPORTED);
  1977.     }
  1978.  
  1979.     // }}}
  1980.     // {{{ _rtrimArrayValues()
  1981.  
  1982.     /**
  1983.      * Right trim all strings in an array
  1984.      *
  1985.      * @param array  $array  the array to be trimmed (passed by reference)
  1986.      * @return void 
  1987.      * @access private
  1988.      */
  1989.     function _rtrimArrayValues(&$array)
  1990.     {
  1991.         foreach ($array as $key => $value{
  1992.             if (is_string($value)) {
  1993.                 $array[$keyrtrim($value);
  1994.             }
  1995.         }
  1996.     }
  1997.  
  1998.     // }}}
  1999.     // {{{ _convertNullArrayValuesToEmpty()
  2000.  
  2001.     /**
  2002.      * Convert all null values in an array to empty strings
  2003.      *
  2004.      * @param array  $array  the array to be de-nullified (passed by reference)
  2005.      * @return void 
  2006.      * @access private
  2007.      */
  2008.     function _convertNullArrayValuesToEmpty(&$array)
  2009.     {
  2010.         foreach ($array as $key => $value{
  2011.             if (is_null($value)) {
  2012.                 $array[$key'';
  2013.             }
  2014.         }
  2015.     }
  2016.  
  2017.     // }}}
  2018. }
  2019.  
  2020. /*
  2021.  * Local variables:
  2022.  * tab-width: 4
  2023.  * c-basic-offset: 4
  2024.  * End:
  2025.  */
  2026.  
  2027. ?>

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