home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / MDB / Common.php next >
Encoding:
PHP Script  |  2005-07-07  |  154.0 KB  |  4,549 lines

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP Version 4                                                        |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  6. // | Stig. S. Bakken, Lukas Smith                                         |
  7. // | All rights reserved.                                                 |
  8. // +----------------------------------------------------------------------+
  9. // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  10. // | API as well as database abstraction for PHP applications.            |
  11. // | This LICENSE is in the BSD license style.                            |
  12. // |                                                                      |
  13. // | Redistribution and use in source and binary forms, with or without   |
  14. // | modification, are permitted provided that the following conditions   |
  15. // | are met:                                                             |
  16. // |                                                                      |
  17. // | Redistributions of source code must retain the above copyright       |
  18. // | notice, this list of conditions and the following disclaimer.        |
  19. // |                                                                      |
  20. // | Redistributions in binary form must reproduce the above copyright    |
  21. // | notice, this list of conditions and the following disclaimer in the  |
  22. // | documentation and/or other materials provided with the distribution. |
  23. // |                                                                      |
  24. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25. // | Lukas Smith nor the names of his contributors may be used to endorse |
  26. // | or promote products derived from this software without specific prior|
  27. // | written permission.                                                  |
  28. // |                                                                      |
  29. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41. // +----------------------------------------------------------------------+
  42. // | Author: Lukas Smith <smith@backendmedia.com>                         |
  43. // +----------------------------------------------------------------------+
  44. //
  45. // $Id: Common.php,v 1.114.4.22 2004/04/08 19:11:58 lsmith Exp $
  46.  
  47. /**
  48.  * @package MDB
  49.  * @author Lukas Smith <smith@backendmedia.com>
  50.  */
  51.  
  52. // }}}
  53. // {{{ MDB_defaultDebugOutput()
  54.  
  55. /**
  56.  * default debug output handler
  57.  *
  58.  * @param object $db reference to an MDB database object
  59.  * @param string $message message that should be appended to the debug
  60.  *       variable
  61.  * @return string the corresponding error message, of FALSE
  62.  * if the error code was unknown
  63.  * @access public
  64.  */
  65. function MDB_defaultDebugOutput(&$db, $message)
  66. {
  67.     $db->debug_output .= $db->database . " $message" . $db->getOption('log_line_break');
  68. }
  69.  
  70. /**
  71.  * MDB_Common: Base class that is extended by each MDB driver
  72.  *
  73.  * @package MDB
  74.  * @category Database
  75.  * @author Lukas Smith <smith@backendmedia.com>
  76.  */
  77. class MDB_Common extends PEAR
  78. {
  79.     // {{{ properties
  80.     /**
  81.     * index of the MDB object withing the global $_MDB_databases array
  82.     * @var integer
  83.     * @access private
  84.     */
  85.     var $database = 0;
  86.  
  87.     /**
  88.     * @var string
  89.     * @access private
  90.     */
  91.     var $host = '';
  92.  
  93.     /**
  94.     * @var string
  95.     * @access private
  96.     */
  97.     var $port = '';
  98.  
  99.     /**
  100.     * @var string
  101.     * @access private
  102.     */
  103.     var $user = '';
  104.  
  105.     /**
  106.     * @var string
  107.     * @access private
  108.     */
  109.     var $password = '';
  110.  
  111.     /**
  112.     * @var string
  113.     * @access private
  114.     */
  115.     var $database_name = '';
  116.  
  117.     /**
  118.     * @var array
  119.     * @access private
  120.     */
  121.     var $supported = array();
  122.  
  123.     /**
  124.     * $options["persistent"] -> boolean persistent connection true|false?
  125.     * $options["debug"] -> integer numeric debug level
  126.     * $options["autofree"] -> boolean
  127.     * $options["lob_buffer_length"] -> integer LOB buffer length
  128.     * $options["log_line_break"] -> string line-break format
  129.     * $options["seqname_format"] -> string pattern for sequence name
  130.     * $options["includelob"] -> boolean
  131.     * $options["includemanager"] -> boolean
  132.     * $options["UseTransactions"] -> boolean
  133.     * $options["optimize"] -> string 'performance' or 'portability'
  134.     * @var array
  135.     * @access private
  136.     */
  137.     var $options = array(
  138.             'persistent' => FALSE,
  139.             'debug' => FALSE,
  140.             'autofree' => FALSE,
  141.             'lob_buffer_length' => 8192,
  142.             'log_line_break' => "\n",
  143.             'seqname_format' => '%s_seq',
  144.             'sequence_col_name' => 'sequence',
  145.             'includelob' => FALSE,
  146.             'includemanager' => FALSE,
  147.             'UseTransactions' => FALSE,
  148.             'optimize' => 'performance',
  149.         );
  150.  
  151.     /**
  152.     * @var string
  153.     * @access private
  154.     */
  155.     var $escape_quotes = '';
  156.  
  157.     /**
  158.     * @var integer
  159.     * @access private
  160.     */
  161.     var $decimal_places = 2;
  162.  
  163.     /**
  164.     * @var string
  165.     * @access private
  166.     */
  167.     var $manager_included_constant = '';
  168.  
  169.     /**
  170.     * @var string
  171.     * @access private
  172.     */
  173.     var $manager_include = '';
  174.  
  175.     /**
  176.     * @var string
  177.     * @access private
  178.     */
  179.     var $manager_class_name = '';
  180.  
  181.     /**
  182.     * @var object
  183.     * @access private
  184.     */
  185.     var $manager;
  186.  
  187.     /**
  188.     * @var array
  189.     * @access private
  190.     */
  191.     var $warnings = array();
  192.  
  193.     /**
  194.     * @var string
  195.     * @access private
  196.     */
  197.     var $debug = '';
  198.  
  199.     /**
  200.     * @var string
  201.     * @access private
  202.     */
  203.     var $debug_output = '';
  204.  
  205.     /**
  206.     * @var boolean
  207.     * @access private
  208.     */
  209.     var $pass_debug_handle = FALSE;
  210.  
  211.     /**
  212.     * @var boolean
  213.     * @access private
  214.     */
  215.     var $auto_commit = TRUE;
  216.  
  217.     /**
  218.     * @var boolean
  219.     * @access private
  220.     */
  221.     var $in_transaction = FALSE;
  222.  
  223.     /**
  224.     * @var integer
  225.     * @access private
  226.     */
  227.     var $first_selected_row = 0;
  228.  
  229.     /**
  230.     * @var integer
  231.     * @access private
  232.     */
  233.     var $selected_row_limit = 0;
  234.  
  235.     /**
  236.     * DB type (mysql, oci8, odbc etc.)
  237.     * @var string
  238.     * @access private
  239.     */
  240.     var $type;
  241.  
  242.     /**
  243.     * @var array
  244.     * @access private
  245.     */
  246.     var $prepared_queries = array();
  247.  
  248.     /**
  249.     * @var array
  250.     * @access private
  251.     */
  252.     var $result_types;
  253.  
  254.     /**
  255.     * @var string
  256.     * @access private
  257.     */
  258.     var $last_query = '';
  259.  
  260.     /**
  261.     * @var integer
  262.     * @access private
  263.     */
  264.     var $fetchmode = MDB_FETCHMODE_ORDERED;
  265.  
  266.     /**
  267.     * @var integer
  268.     * @access private
  269.     */
  270.     var $affected_rows = -1;
  271.  
  272.     /**
  273.     * @var array
  274.     * @access private
  275.     */
  276.     var $lobs = array();
  277.  
  278.     /**
  279.     * @var array
  280.     * @access private
  281.     */
  282.     var $clobs = array();
  283.  
  284.     /**
  285.     * @var array
  286.     * @access private
  287.     */
  288.     var $blobs = array();
  289.  
  290.     // }}}
  291.     // {{{ constructor
  292.  
  293.     /**
  294.      * Constructor
  295.      */
  296.     function MDB_Common()
  297.     {
  298.         $database = count($GLOBALS['_MDB_databases']) + 1;
  299.         $GLOBALS['_MDB_databases'][$database] = &$this;
  300.         $this->database = $database;
  301.  
  302.         $this->PEAR('MDB_Error');
  303.         $this->supported = array();
  304.         $this->errorcode_map = array();
  305.         $this->fetchmode = MDB_FETCHMODE_ORDERED;
  306.     }
  307.  
  308.     // }}}
  309.     // {{{ __toString()
  310.  
  311.     /**
  312.      * String conversation
  313.      *
  314.      * @return string
  315.      * @access public
  316.      */
  317.     function __toString()
  318.     {
  319.         $info = get_class($this);
  320.         $info .= ': (phptype = ' . $this->phptype . ', dbsyntax = ' . $this->dbsyntax . ')';
  321.         if ($this->connection) {
  322.             $info .= ' [connected]';
  323.         }
  324.         return($info);
  325.     }
  326.  
  327.     // }}}
  328.     // {{{ errorCode()
  329.  
  330.     /**
  331.      * Map native error codes to MDB's portable ones.  Requires that
  332.      * the DB implementation's constructor fills in the $errorcode_map
  333.      * property.
  334.      *
  335.      * @param mixed $nativecode the native error code, as returned by the
  336.      *      backend database extension (string or integer)
  337.      * @return int a portable MDB error code, or FALSE if this MDB
  338.      *      implementation has no mapping for the given error code.
  339.      * @access public
  340.      */
  341.     function errorCode($nativecode)
  342.     {
  343.         if (isset($this->errorcode_map[$nativecode])) {
  344.             return($this->errorcode_map[$nativecode]);
  345.         }
  346.         // Fall back to MDB_ERROR if there was no mapping.
  347.         return(MDB_ERROR);
  348.     }
  349.  
  350.     // }}}
  351.     // {{{ errorMessage()
  352.  
  353.     /**
  354.      * Map a MDB error code to a textual message.  This is actually
  355.      * just a wrapper for MDB::errorMessage().
  356.      *
  357.      * @param integer $dbcode the MDB error code
  358.      * @return string the corresponding error message, of FALSE
  359.      *      if the error code was unknown
  360.      * @access public
  361.      */
  362.     function errorMessage($dbcode)
  363.     {
  364.         return(MDB::errorMessage($this->errorcode_map[$dbcode]));
  365.     }
  366.  
  367.     // }}}
  368.     // {{{ raiseError()
  369.  
  370.     /**
  371.      * This method is used to communicate an error and invoke error
  372.      * callbacks etc.  Basically a wrapper for PEAR::raiseError
  373.      * without the message string.
  374.      *
  375.      * @param mixed $code integer error code, or a PEAR error object (all
  376.      *      other parameters are ignored if this parameter is an object
  377.      * @param int $mode error mode, see PEAR_Error docs
  378.      * @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the
  379.      *      error level (E_USER_NOTICE etc).  If error mode is
  380.      *      PEAR_ERROR_CALLBACK, this is the callback function, either as a
  381.      *      function name, or as an array of an object and method name. For
  382.      *      other error modes this parameter is ignored.
  383.      * @param string $userinfo Extra debug information.  Defaults to the last
  384.      *      query and native error code.
  385.      * @param mixed $nativecode Native error code, integer or string depending
  386.      *      the backend.
  387.      * @return object a PEAR error object
  388.      * @access public
  389.      * @see PEAR_Error
  390.      */
  391.     function &raiseError($code = MDB_ERROR, $mode = NULL, $options = NULL,
  392.         $userinfo = NULL, $nativecode = NULL)
  393.     {
  394.         // The error is yet a MDB error object
  395.         if (is_object($code)) {
  396.             // because we the static PEAR::raiseError, our global
  397.             // handler should be used if it is set
  398.             if ($mode === null && !empty($this->_default_error_mode)) {
  399.                 $mode    = $this->_default_error_mode;
  400.                 $options = $this->_default_error_options;
  401.             }
  402.             $err = PEAR::raiseError($code, NULL, $mode, $options, NULL, NULL, TRUE);
  403.             return($err);
  404.         }
  405.  
  406.         if ($userinfo === NULL) {
  407.             $userinfo = $this->last_query;
  408.         }
  409.  
  410.         if ($nativecode) {
  411.             $userinfo .= ' [nativecode=' . trim($nativecode) . ']';
  412.         }
  413.  
  414.         $err = PEAR::raiseError(NULL, $code, $mode, $options, $userinfo, 'MDB_Error', TRUE);
  415.         return($err);
  416.     }
  417.  
  418.     // }}}
  419.     // {{{ errorNative()
  420.  
  421.     /**
  422.      * returns an errormessage, provides by the database
  423.      *
  424.      * @return mixed MDB_Error or message
  425.      * @access public
  426.      */
  427.     function errorNative()
  428.     {
  429.         return($this->raiseError(MDB_ERROR_NOT_CAPABLE));
  430.     }
  431.  
  432.     // }}}
  433.     // {{{ resetWarnings()
  434.  
  435.     /**
  436.      * reset the warning array
  437.      *
  438.      * @access public
  439.      */
  440.     function resetWarnings()
  441.     {
  442.         $this->warnings = array();
  443.     }
  444.  
  445.     // }}}
  446.     // {{{ getWarnings()
  447.  
  448.     /**
  449.      * get all warnings in reverse order.
  450.      * This means that the last warning is the first element in the array
  451.      *
  452.      * @return array with warnings
  453.      * @access public
  454.      * @see resetWarnings()
  455.      */
  456.     function getWarnings()
  457.     {
  458.         return array_reverse($this->warnings);
  459.     }
  460.  
  461.     // }}}
  462.     // {{{ setOption()
  463.  
  464.     /**
  465.      * set the option for the db class
  466.      *
  467.      * @param string $option option name
  468.      * @param mixed $value value for the option
  469.      * @return mixed MDB_OK or MDB_Error
  470.      * @access public
  471.      */
  472.     function setOption($option, $value)
  473.     {
  474.         if (isset($this->options[$option])) {
  475.             $this->options[$option] = $value;
  476.             return MDB_OK;
  477.         }
  478.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option"));
  479.     }
  480.  
  481.     // }}}
  482.     // {{{ getOption()
  483.  
  484.     /**
  485.      * returns the value of an option
  486.      *
  487.      * @param string $option option name
  488.      * @return mixed the option value or error object
  489.      * @access public
  490.      */
  491.     function getOption($option)
  492.     {
  493.         if (isset($this->options[$option])) {
  494.             return($this->options[$option]);
  495.         }
  496.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option"));
  497.     }
  498.  
  499.     // }}}
  500.     // {{{ captureDebugOutput()
  501.  
  502.     /**
  503.      * set a debug handler
  504.      *
  505.      * @param string $capture name of the function that should be used in
  506.      *      debug()
  507.      * @access public
  508.      * @see debug()
  509.      */
  510.     function captureDebugOutput($capture)
  511.     {
  512.         $this->pass_debug_handle = $capture;
  513.         $this->debug = ($capture ? 'MDB_defaultDebugOutput' : '');
  514.     }
  515.  
  516.     // }}}
  517.     // {{{ debug()
  518.  
  519.     /**
  520.      * set a debug message
  521.      *
  522.      * @param string $message Message with information for the user.
  523.      * @access public
  524.      */
  525.     function debug($message)
  526.     {
  527.         if (strcmp($function = $this->debug, '')) {
  528.             if ($this->pass_debug_handle) {
  529.                 $function($this, $message);
  530.             } else {
  531.                 $function($message);
  532.             }
  533.         }
  534.     }
  535.  
  536.     // }}}
  537.     // {{{ debugOutput()
  538.  
  539.     /**
  540.      * output debug info
  541.      *
  542.      * @return string content of the debug_output class variable
  543.      * @access public
  544.      */
  545.     function debugOutput()
  546.     {
  547.         return($this->debug_output);
  548.     }
  549.  
  550.     // }}}
  551.     // {{{ setError() (deprecated)
  552.  
  553.     /**
  554.      * set an error (deprecated)
  555.      *
  556.      * @param string $scope Scope of the error message
  557.      *     (usually the method tht caused the error)
  558.      * @param string $message Message with information for the user.
  559.      * @return boolean FALSE
  560.      * @access private
  561.      */
  562.     function setError($scope, $message)
  563.     {
  564.         $this->last_error = $message;
  565.         $this->debug($scope . ': ' . $message);
  566.         if (($function = $this->error_handler) != '') {
  567.             $error = array(
  568.                 'Scope' => $scope,
  569.                 'Message' => $message
  570.             );
  571.             $function($this, $error);
  572.         }
  573.         return(0);
  574.     }
  575.  
  576.     // }}}
  577.     // {{{ setErrorHandler() (deprecated)
  578.  
  579.     /**
  580.      * Specify a function that is called when an error occurs.
  581.      *
  582.      * @param string $function Name of the function that will be called on
  583.      *      error. If an empty string is specified, no handler function is
  584.      *      called on error. The error handler function receives two arguments.
  585.      *      The first argument a reference to the driver class object that
  586.      *      triggered the error.
  587.      *
  588.      *      The second argument is a reference to an associative array that
  589.      *      provides details about the error that occured. These details provide
  590.      *      more information than it is returned by the MetabaseError function.
  591.      *
  592.      *      These are the currently supported error detail entries:
  593.      *
  594.      *      Scope
  595.      *       String that indicates the scope of the driver object class
  596.      *       within which the error occured.
  597.      *
  598.      *      Message
  599.      *       Error message as is returned by the MetabaseError function.
  600.      * @return string name of last function
  601.      * @access public
  602.      */
  603.     function setErrorHandler($function)
  604.     {
  605.         $last_function = $this->error_handler;
  606.         $this->error_handler = $function;
  607.         return($last_function);
  608.     }
  609.  
  610.     // }}}
  611.     // {{{ error() (deprecated)
  612.  
  613.     /**
  614.      * Retrieve the error message text associated with the last operation that
  615.      * failed. Some functions may fail but they do not return the reason that
  616.      * makes them to fail. This function is meant to retrieve a textual
  617.      * description of the failure cause.
  618.      *
  619.      * @return string the error message text associated with the last failure.
  620.      * @access public
  621.      */
  622.     function error()
  623.     {
  624.         return($this->last_error);
  625.     }
  626.  
  627.     // }}}
  628.     // {{{ _quote()
  629.  
  630.     /**
  631.      * Quotes a string so it can be safely used in a query. It will quote
  632.      * the text so it can safely be used within a query.
  633.      *
  634.      * @param string $text the input string to quote
  635.      * @return string quoted string
  636.      * @access private
  637.      */
  638.     function _quote($text)
  639.     {
  640.         if (strcmp($this->escape_quotes, "'")) {
  641.             $text = str_replace($this->escape_quotes, $this->escape_quotes . $this->escape_quotes, $text);
  642.         }
  643.         return str_replace("'", $this->escape_quotes . "'", $text);
  644.     }
  645.  
  646.     // }}}
  647.     // {{{ quoteIdentifier()
  648.  
  649.     /**
  650.      * Quote a string so it can be safely used as a table or column name
  651.      *
  652.      * Delimiting style depends on which database driver is being used.
  653.      *
  654.      * NOTE: just because you CAN use delimited identifiers doesn't mean
  655.      * you SHOULD use them.  In general, they end up causing way more
  656.      * problems than they solve.
  657.      *
  658.      * Portability is broken by using the following characters inside
  659.      * delimited identifiers:
  660.      *   + backtick (<kbd>`</kbd>) -- due to MySQL
  661.      *   + double quote (<kbd>"</kbd>) -- due to Oracle
  662.      *   + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
  663.      *
  664.      * Delimited identifiers are known to generally work correctly under
  665.      * the following drivers:
  666.      *   + mssql
  667.      *   + mysql
  668.      *   + mysqli
  669.      *   + oci8
  670.      *   + odbc(access)
  671.      *   + odbc(db2)
  672.      *   + pgsql
  673.      *   + sqlite
  674.      *   + sybase
  675.      *
  676.      * InterBase doesn't seem to be able to use delimited identifiers
  677.      * via PHP 4.  They work fine under PHP 5.
  678.      *
  679.      * @param string $str  identifier name to be quoted
  680.      *
  681.      * @return string  quoted identifier string
  682.      *
  683.      * @access public
  684.      */
  685.     function quoteIdentifier($str)
  686.     {
  687.         return '"' . str_replace('"', '""', $str) . '"';
  688.     }
  689.  
  690.     // }}}
  691.     // {{{ _loadModule()
  692.  
  693.     /**
  694.      * loads an module
  695.      *
  696.      * @param string $scope information about what method is being loaded,
  697.      *      that is used for error messages
  698.      * @param string $module name of the module that should be loaded
  699.      *      (only used for error messages)
  700.      * @param string $included_constant name of the constant that should be
  701.      *      defined when the module has been loaded
  702.      * @param string $include name of the script that includes the module
  703.      * @access private
  704.      */
  705.     function _loadModule($scope, $module, $included_constant, $include)
  706.     {
  707.         if (strlen($included_constant) == 0 || !defined($included_constant)) {
  708.             if($include) {
  709.                 $include = 'MDB/Modules/'.$include;
  710.                 if(MDB::isError($debug = $this->getOption('debug')) || $debug > 2) {
  711.                     include_once($include);
  712.                 } else {
  713.                     @include_once($include);
  714.                 }
  715.             } else {
  716.                 return($this->raiseError(MDB_ERROR_LOADMODULE, NULL, NULL,
  717.                     $scope . ': it was not specified an existing ' . $module . ' file (' . $include . ')'));
  718.             }
  719.         }
  720.         return(MDB_OK);
  721.     }
  722.  
  723.     // }}}
  724.     // {{{ loadLob()
  725.  
  726.     /**
  727.      * loads the LOB module
  728.      *
  729.      * @param string $scope information about what method is being loaded,
  730.      *                       that is used for error messages
  731.      * @access public
  732.      */
  733.     function loadLob($scope = '')
  734.     {
  735.         if (defined('MDB_LOB_INCLUDED')) {
  736.             return(MDB_OK);
  737.         }
  738.         $result = $this->_loadModule($scope, 'LOB',
  739.             'MDB_LOB_INCLUDED', 'LOB.php');
  740.         if (MDB::isError($result)) {
  741.             return($result);
  742.         }
  743.         return(MDB_OK);
  744.     }
  745.  
  746.     // }}}
  747.     // {{{ loadManager()
  748.  
  749.     /**
  750.      * loads the Manager module
  751.      *
  752.      * @param string $scope information about what method is being loaded,
  753.      *                       that is used for error messages
  754.      * @access public
  755.      */
  756.     function loadManager($scope = '')
  757.     {
  758.         if (isset($this->manager) && is_object($this->manager)) {
  759.             return(MDB_OK);
  760.         }
  761.         $result = $this->_loadModule($scope, 'Manager',
  762.             'MDB_MANAGER_'.strtoupper($this->phptype).'_INCLUDED',
  763.             'Manager/'.$this->phptype.'.php');
  764.         if (MDB::isError($result)) {
  765.             return($result);
  766.         }
  767.         $class_name = 'MDB_Manager_'.$this->dbsyntax;
  768.         if (!class_exists($class_name)) {
  769.             return($this->raiseError(MDB_ERROR_LOADMODULE, NULL, NULL,
  770.                 'Unable to load extension'));
  771.         }
  772.         @$this->manager = new $class_name;
  773.         return(MDB_OK);
  774.     }
  775.  
  776.     // }}}
  777.     // {{{ autoCommit()
  778.  
  779.     /**
  780.      * Define whether database changes done on the database be automatically
  781.      * committed. This function may also implicitly start or end a transaction.
  782.      *
  783.      * @param boolean $auto_commit flag that indicates whether the database
  784.      *      changes should be committed right after executing every query
  785.      *      statement. If this argument is 0 a transaction implicitly started.
  786.      *      Otherwise, if a transaction is in progress it is ended by committing
  787.      *      any database changes that were pending.
  788.      * @return mixed MDB_OK on success, a MDB error on failure
  789.      * @access public
  790.      */
  791.     function autoCommit($auto_commit)
  792.     {
  793.         $this->debug('AutoCommit: ' . ($auto_commit ? 'On' : 'Off'));
  794.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  795.             'Auto-commit transactions: transactions are not supported'));
  796.     }
  797.  
  798.     // }}}
  799.     // {{{ commit()
  800.  
  801.     /**
  802.      * Commit the database changes done during a transaction that is in
  803.      * progress. This function may only be called when auto-committing is
  804.      * disabled, otherwise it will fail. Therefore, a new transaction is
  805.      * implicitly started after committing the pending changes.
  806.      *
  807.      * @return mixed MDB_OK on success, a MDB error on failure
  808.      * @access public
  809.      */
  810.     function commit()
  811.     {
  812.         $this->debug('Commit Transaction');
  813.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  814.             'Commit transaction: commiting transactions are not supported'));
  815.     }
  816.  
  817.     // }}}
  818.     // {{{ rollback()
  819.  
  820.     /**
  821.      * Cancel any database changes done during a transaction that is in
  822.      * progress. This function may only be called when auto-committing is
  823.      * disabled, otherwise it will fail. Therefore, a new transaction is
  824.      * implicitly started after canceling the pending changes.
  825.      *
  826.      * @return mixed MDB_OK on success, a MDB error on failure
  827.      * @access public
  828.      */
  829.     function rollback()
  830.     {
  831.         $this->debug('Rollback Transaction');
  832.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  833.             'Rollback transaction: rolling back transactions are not supported'));
  834.     }
  835.  
  836.     // }}}
  837.     // {{{ disconnect()
  838.  
  839.     /**
  840.      * Log out and disconnect from the database.
  841.      *
  842.      * @return mixed TRUE on success, FALSE if not connected and error
  843.      *                object on error
  844.      * @access public
  845.      */
  846.     function disconnect()
  847.     {
  848.         if ($this->in_transaction && !MDB::isError($this->rollback()) && !MDB::isError($this->autoCommit(TRUE))) {
  849.             $this->in_transaction = FALSE;
  850.         }
  851.         return($this->_close());
  852.     }
  853.  
  854.     // }}}
  855.     // {{{ _close()
  856.  
  857.     /**
  858.      * all the RDBMS specific things needed to close a DB connection
  859.      *
  860.      * @access private
  861.      */
  862.     function _close()
  863.     {
  864.         unset($GLOBALS['_MDB_databases'][$this->database]);
  865.     }
  866.  
  867.     // }}}
  868.     // {{{ setDatabase()
  869.  
  870.     /**
  871.      * Select a different database
  872.      *
  873.      * @param string $name name of the database that should be selected
  874.      * @return string name of the database previously connected to
  875.      * @access public
  876.      */
  877.     function setDatabase($name)
  878.     {
  879.         $previous_database_name = $this->database_name;
  880.         $this->database_name = $name;
  881.         return($previous_database_name);
  882.     }
  883.  
  884.     // }}}
  885.     // {{{ setDSN()
  886.  
  887.     /**
  888.      * set the DSN
  889.      *
  890.      * @param mixed     $dsninfo    DSN string or array
  891.      * @return MDB_OK
  892.      * @access public
  893.      */
  894.     function setDSN($dsn)
  895.     {
  896.         $dsninfo = MDB::parseDSN($dsn);
  897.         if(isset($dsninfo['hostspec'])) {
  898.             $this->host = $dsninfo['hostspec'];
  899.         }
  900.         if(isset($dsninfo['port'])) {
  901.             $this->port = $dsninfo['port'];
  902.         }
  903.         if(isset($dsninfo['username'])) {
  904.             $this->user = $dsninfo['username'];
  905.         }
  906.         if(isset($dsninfo['password'])) {
  907.             $this->password = $dsninfo['password'];
  908.         }
  909.         if(isset($dsninfo['database'])) {
  910.             $this->database_name = $dsninfo['database'];
  911.         }
  912.         return(MDB_OK);
  913.     }
  914.  
  915.     // }}}
  916.     // {{{ getDSN()
  917.  
  918.     /**
  919.      * return the DSN as a string
  920.      *
  921.      * @param string     $type    type to return
  922.      * @return mixed DSN in the chosen type
  923.      * @access public
  924.      */
  925.     function getDSN($type = 'string')
  926.     {
  927.         switch($type) {
  928.             case 'array':
  929.                 $dsn = array(
  930.                     'phptype' => $this->phptype,
  931.                     'username' => $this->user,
  932.                     'password' => $this->password,
  933.                     'hostspec' => $this->host,
  934.                     'database' => $this->database_name
  935.                 );
  936.                 break;
  937.             default:
  938.                 $dsn = $this->phptype.'://'.$this->user.':'
  939.                     .$this->password.'@'.$this->host
  940.                     .($this->port ? (':'.$this->port) : '')
  941.                     .'/'.$this->database_name;
  942.                 break;
  943.         }
  944.         return($dsn);
  945.     }
  946.  
  947.     // }}}
  948.     // {{{ createDatabase()
  949.  
  950.     /**
  951.      * create a new database
  952.      *
  953.      * @param string $name name of the database that should be created
  954.      * @return mixed MDB_OK on success, a MDB error on failure
  955.      * @access public
  956.      */
  957.     function createDatabase($name)
  958.     {
  959.         $result = $this->loadManager('Create database');
  960.         if (MDB::isError($result)) {
  961.             return($result);
  962.         }
  963.         return($this->manager->createDatabase($this, $name));
  964.     }
  965.  
  966.     // }}}
  967.     // {{{ dropDatabase()
  968.  
  969.     /**
  970.      * drop an existing database
  971.      *
  972.      * @param string $name name of the database that should be dropped
  973.      * @return mixed MDB_OK on success, a MDB error on failure
  974.      * @access public
  975.      */
  976.     function dropDatabase($name)
  977.     {
  978.         $result = $this->loadManager('Drop database');
  979.         if (MDB::isError($result)) {
  980.             return($result);
  981.         }
  982.         return($this->manager->dropDatabase($this, $name));
  983.     }
  984.  
  985.     // }}}
  986.     // {{{ createTable()
  987.  
  988.     /**
  989.      * create a new table
  990.      *
  991.      * @param string $name Name of the database that should be created
  992.      * @param array $fields Associative array that contains the definition of
  993.      *      each field of the new table. The indexes of the array entries are
  994.      *      the names of the fields of the table an the array entry values are
  995.      *      associative arrays like those that are meant to be passed with the
  996.      *      field definitions to get[Type]Declaration() functions.
  997.      *
  998.      *      Example
  999.      *        array(
  1000.      *            'id' => array(
  1001.      *                'type' => 'integer',
  1002.      *                'unsigned' => 1
  1003.      *                'notnull' => 1
  1004.      *                'default' => 0
  1005.      *            ),
  1006.      *            'name' => array(
  1007.      *                'type' => 'text',
  1008.      *                'length' => 12
  1009.      *            ),
  1010.      *            'password' => array(
  1011.      *                'type' => 'text',
  1012.      *                'length' => 12
  1013.      *            )
  1014.      *        );
  1015.      * @return mixed MDB_OK on success, a MDB error on failure
  1016.      * @access public
  1017.      */
  1018.     function createTable($name, $fields)
  1019.     {
  1020.         $result = $this->loadManager('Create table');
  1021.         if (MDB::isError($result)) {
  1022.             return($result);
  1023.         }
  1024.         return($this->manager->createTable($this, $name, $fields));
  1025.     }
  1026.  
  1027.     // }}}
  1028.     // {{{ dropTable()
  1029.  
  1030.     /**
  1031.      * drop an existing table
  1032.      *
  1033.      * @param string $name name of the table that should be dropped
  1034.      * @return mixed MDB_OK on success, a MDB error on failure
  1035.      * @access public
  1036.      */
  1037.     function dropTable($name)
  1038.     {
  1039.         $result = $this->loadManager('Drop table');
  1040.         if (MDB::isError($result)) {
  1041.             return($result);
  1042.         }
  1043.         return($this->manager->dropTable($this, $name));
  1044.     }
  1045.  
  1046.     // }}}
  1047.     // {{{ alterTable()
  1048.  
  1049.     /**
  1050.      * alter an existing table
  1051.      *
  1052.      * @param string $name name of the table that is intended to be changed.
  1053.      * @param array  $changes associative array that contains the details of
  1054.      *       each type of change that is intended to be performed. The types of
  1055.      *       changes that are currently supported are defined as follows:
  1056.      *
  1057.      *  name
  1058.      *      New name for the table.
  1059.      *
  1060.      *  AddedFields
  1061.      *      Associative array with the names of fields to be added as indexes of
  1062.      *      the array. The value of each entry of the array should be set to
  1063.      *      another associative array with the properties of the fields to be
  1064.      *      added. The properties of the fields should be the same as defined by
  1065.      *      the Metabase parser.
  1066.      *
  1067.      *      Additionally, there should be an entry named Declaration that is
  1068.      *      expected to contain the portion of the field declaration already in
  1069.      *       DBMS specific SQL code as it is used in the CREATE TABLE statement.
  1070.      *
  1071.      *  RemovedFields
  1072.      *      Associative array with the names of fields to be removed as indexes of
  1073.      *      the array. Currently the values assigned to each entry are ignored. An
  1074.      *      empty array should be used for future compatibility.
  1075.      *
  1076.      *  RenamedFields
  1077.      *      Associative array with the names of fields to be renamed as indexes of
  1078.      *      the array. The value of each entry of the array should be set to another
  1079.      *      associative array with the entry named name with the new field name and
  1080.      *      the entry named Declaration that is expected to contain the portion of
  1081.      *      the field declaration already in DBMS specific SQL code as it is used
  1082.      *      in the CREATE TABLE statement.
  1083.      *
  1084.      *  ChangedFields
  1085.      *      Associative array with the names of the fields to be changed as indexes
  1086.      *      of the array. Keep in mind that if it is intended to change either the
  1087.      *      name of a field and any other properties, the ChangedFields array
  1088.      *      entries should have the new names of the fields as array indexes.
  1089.      *
  1090.      *      The value of each entry of the array should be set to another
  1091.      *      associative array with the properties of the fields to that are meant
  1092.      *      to be changed as array entries. These entries should be assigned to the
  1093.      *      new values of the respective properties. The properties of the fields
  1094.      *      should be the* same as defined by the Metabase parser.
  1095.      *
  1096.      *      If the default property is meant to be added, removed or changed, there
  1097.      *      should also be an entry with index ChangedDefault assigned to 1.
  1098.      *      Similarly, if the notnull constraint is to be added or removed, there
  1099.      *      should also be an entry with index ChangedNotNull assigned to 1.
  1100.      *
  1101.      *      Additionally, there should be an entry named Declaration that is
  1102.      *      expected to contain the portion of the field changed declaration
  1103.      *      already in DBMS specific SQL code as it is used in the CREATE TABLE
  1104.      *      statement.
  1105.      *
  1106.      *  Example
  1107.      *      array(
  1108.      *          'name' => 'userlist',
  1109.      *          'AddedFields' => array(
  1110.      *              'quota' => array(
  1111.      *                  'type' => 'integer',
  1112.      *                  'unsigned' => 1,
  1113.      *                  'Declaration' => 'quota INT'
  1114.      *              )
  1115.      *          ),
  1116.      *          'RemovedFields' => array(
  1117.      *              'file_limit' => array(),
  1118.      *              'time_limit' => array()
  1119.      *          ),
  1120.      *          'ChangedFields' => array(
  1121.      *              'gender' => array(
  1122.      *                  'default' => 'M',
  1123.      *                  'ChangeDefault' => 1,
  1124.      *                  'Declaration' => "gender CHAR(1) DEFAULT 'M'"
  1125.      *              )
  1126.      *          ),
  1127.      *          'RenamedFields' => array(
  1128.      *              'sex' => array(
  1129.      *                  'name' => 'gender',
  1130.      *                  'Declaration' => "gender CHAR(1) DEFAULT 'M'"
  1131.      *              )
  1132.      *          )
  1133.      *      )
  1134.      *
  1135.      * @param boolean $check indicates whether the function should just check
  1136.      *       if the DBMS driver can perform the requested table alterations if
  1137.      *       the value is TRUE or actually perform them otherwise.
  1138.      * @return mixed MDB_OK on success, a MDB error on failure
  1139.      * @access public
  1140.      */
  1141.     function alterTable($name, $changes, $check)
  1142.     {
  1143.         $result = $this->loadManager('Alter table');
  1144.         if (MDB::isError($result)) {
  1145.             return($result);
  1146.         }
  1147.         return($this->manager->alterTable($this, $name, $changes, $check));
  1148.     }
  1149.  
  1150.     // }}}
  1151.     // {{{ listDatabases()
  1152.  
  1153.     /**
  1154.      * list all databases
  1155.      *
  1156.      * @return mixed data array on success, a MDB error on failure
  1157.      * @access public
  1158.      */
  1159.     function listDatabases()
  1160.     {
  1161.         $result = $this->loadManager('List databases');
  1162.         if (MDB::isError($result)) {
  1163.             return($result);
  1164.         }
  1165.         return($this->manager->listDatabases($this));
  1166.     }
  1167.  
  1168.     // }}}
  1169.     // {{{ listUsers()
  1170.  
  1171.     /**
  1172.      * list all users
  1173.      *
  1174.      * @return mixed data array on success, a MDB error on failure
  1175.      * @access public
  1176.      */
  1177.     function listUsers()
  1178.     {
  1179.         $result = $this->loadManager('List users');
  1180.         if (MDB::isError($result)) {
  1181.             return($result);
  1182.         }
  1183.         return($this->manager->listUsers($this));
  1184.     }
  1185.  
  1186.     // }}}
  1187.     // {{{ listViews()
  1188.  
  1189.     /**
  1190.      * list all viewes in the current database
  1191.      *
  1192.      * @return mixed data array on success, a MDB error on failure
  1193.      * @access public
  1194.      */
  1195.     function listViews()
  1196.     {
  1197.         $result = $this->loadManager('List views');
  1198.         if (MDB::isError($result)) {
  1199.             return($result);
  1200.         }
  1201.         return($this->manager->listViews($this));
  1202.     }
  1203.  
  1204.     // }}}
  1205.     // {{{ listFunctions()
  1206.  
  1207.     /**
  1208.      * list all functions in the current database
  1209.      *
  1210.      * @return mixed data array on success, a MDB error on failure
  1211.      * @access public
  1212.      */
  1213.     function listFunctions()
  1214.     {
  1215.         $result = $this->loadManager('List functions');
  1216.         if (MDB::isError($result)) {
  1217.             return($result);
  1218.         }
  1219.         return($this->manager->listFunctions($this));
  1220.     }
  1221.  
  1222.     // }}}
  1223.     // {{{ listTables()
  1224.  
  1225.     /**
  1226.      * list all tables in the current database
  1227.      *
  1228.      * @return mixed data array on success, a MDB error on failure
  1229.      * @access public
  1230.      */
  1231.     function listTables()
  1232.     {
  1233.         $result = $this->loadManager('List tables');
  1234.         if (MDB::isError($result)) {
  1235.             return($result);
  1236.         }
  1237.         return($this->manager->listTables($this));
  1238.     }
  1239.  
  1240.     // }}}
  1241.     // {{{ listTableFields()
  1242.  
  1243.     /**
  1244.      * list all fields in a tables in the current database
  1245.      *
  1246.      * @param string $table name of table that should be used in method
  1247.      * @return mixed data array on success, a MDB error on failure
  1248.      * @access public
  1249.      */
  1250.     function listTableFields($table)
  1251.     {
  1252.         $result = $this->loadManager('List table fields');
  1253.         if (MDB::isError($result)) {
  1254.             return($result);
  1255.         }
  1256.         return($this->manager->listTableFields($this, $table));
  1257.     }
  1258.  
  1259.     // }}}
  1260.     // {{{ getTableFieldDefinition()
  1261.  
  1262.     /**
  1263.      * get the stucture of a field into an array
  1264.      *
  1265.      * @param string $table name of table that should be used in method
  1266.      * @param string $fields name of field that should be used in method
  1267.      * @return mixed data array on success, a MDB error on failure
  1268.      * @access public
  1269.      */
  1270.     function getTableFieldDefinition($table, $field)
  1271.     {
  1272.         $result = $this->loadManager('Get table field definition');
  1273.         if (MDB::isError($result)) {
  1274.             return($result);
  1275.         }
  1276.         return($this->manager->getTableFieldDefinition($this, $table, $field));
  1277.     }
  1278.  
  1279.     // }}}
  1280.     // {{{ getFieldDeclaration()
  1281.  
  1282.     /**
  1283.      * get declaration of a field
  1284.      *
  1285.      * @param string $field_name name of the field to be created
  1286.      * @param string $field associative array with the name of the properties
  1287.      *       of the field being declared as array indexes. Currently, the types
  1288.      *       of supported field properties are as follows:
  1289.      *
  1290.      *       default
  1291.      *           Boolean value to be used as default for this field.
  1292.      *
  1293.      *       notnull
  1294.      *           Boolean flag that indicates whether this field is constrained
  1295.      *           to not be set to NULL.
  1296.      * @return mixed string on success, a MDB error on failure
  1297.      * @access public
  1298.      */
  1299.     function getFieldDeclaration($field_name, $field)
  1300.     {
  1301.         $result = $this->loadManager('Get table field definition');
  1302.         if (MDB::isError($result)) {
  1303.             return($result);
  1304.         }
  1305.         return($this->manager->getFieldDeclaration($this, $field_name, $field));
  1306.     }
  1307.  
  1308.     // }}}
  1309.     // {{{ getFieldDeclarationList()
  1310.  
  1311.     /**
  1312.      * get declaration of a number of field in bulk
  1313.      *
  1314.      * @param string $fields a multidimensional associative array.
  1315.      * The first dimension determines the field name, while the second
  1316.      * dimension is keyed with the name of the properties
  1317.      *       of the field being declared as array indexes. Currently, the types
  1318.      *       of supported field properties are as follows:
  1319.      *
  1320.      *       default
  1321.      *           Boolean value to be used as default for this field.
  1322.      *
  1323.      *       notnull
  1324.      *           Boolean flag that indicates whether this field is constrained
  1325.      *           to not be set to NULL.
  1326.      *
  1327.      *       default
  1328.      *           Boolean value to be used as default for this field.
  1329.      *
  1330.      *       notnull
  1331.      *           Boolean flag that indicates whether this field is constrained
  1332.      *           to not be set to NULL.
  1333.      * @return mixed string on success, a MDB error on failure
  1334.      * @access public
  1335.      */
  1336.     function getFieldDeclarationList($fields)
  1337.     {
  1338.         $result = $this->loadManager('Get table field list');
  1339.         if (MDB::isError($result)) {
  1340.             return($result);
  1341.         }
  1342.         return($this->manager->getFieldDeclarationList($this, $fields));
  1343.     }
  1344.  
  1345.     // }}}
  1346.     // {{{ _isSequenceName()
  1347.  
  1348.     /**
  1349.      * list all tables in the current database
  1350.      *
  1351.      * @param string $sqn string that containts name of a potential sequence
  1352.      * @return mixed name of the sequence if $sqn is a name of a sequence, else FALSE
  1353.      * @access private
  1354.      */
  1355.     function _isSequenceName($sqn)
  1356.     {
  1357.         $result = $this->loadManager('is sequence name');
  1358.         if (MDB::isError($result)) {
  1359.             return($result);
  1360.         }
  1361.         return($this->manager->_isSequenceName($this, $sqn));
  1362.     }
  1363.  
  1364.     // }}}
  1365.     // {{{ createIndex()
  1366.  
  1367.     /**
  1368.      * get the stucture of a field into an array
  1369.      *
  1370.      * @param string $table name of the table on which the index is to be
  1371.      *       created
  1372.      * @param string $name name of the index to be created
  1373.      * @param array $definition associative array that defines properties of
  1374.      *       the index to be created. Currently, only one property named FIELDS
  1375.      *       is supported. This property is also an associative with the names
  1376.      *       of the index fields as array indexes. Each entry of this array is
  1377.      *       set to another type of associative array that specifies properties
  1378.      *       of the index that are specific to each field.
  1379.      *
  1380.      *       Currently, only the sorting property is supported. It should be
  1381.      *       used to define the sorting direction of the index. It may be set
  1382.      *       to either ascending or descending. Not all DBMS support index
  1383.      *       sorting direction configuration. The DBMS drivers of those that do
  1384.      *       not support it ignore this property. Use the function support() to
  1385.      *       determine whether the DBMS driver can manage indexes.
  1386.      *
  1387.      *       Example
  1388.      *          array(
  1389.      *              'FIELDS' => array(
  1390.      *                  'user_name' => array(
  1391.      *                      'sorting' => 'ascending'
  1392.      *                  ),
  1393.      *                  'last_login' => array()
  1394.      *              )
  1395.      *          )
  1396.      * @return mixed MDB_OK on success, a MDB error on failure
  1397.      * @access public
  1398.      */
  1399.     function createIndex($table, $name, $definition)
  1400.     {
  1401.         $result = $this->loadManager('Create index');
  1402.         if (MDB::isError($result)) {
  1403.             return($result);
  1404.         }
  1405.         return($this->manager->createIndex($this, $table, $name, $definition));
  1406.     }
  1407.  
  1408.     // }}}
  1409.     // {{{ dropIndex()
  1410.  
  1411.     /**
  1412.      * drop existing index
  1413.      *
  1414.      * @param string $table name of table that should be used in method
  1415.      * @param string $name name of the index to be dropped
  1416.      * @return mixed MDB_OK on success, a MDB error on failure
  1417.      * @access public
  1418.      */
  1419.     function dropIndex($table, $name)
  1420.     {
  1421.         $result = $this->loadManager('Drop index');
  1422.         if (MDB::isError($result)) {
  1423.             return($result);
  1424.         }
  1425.         return($this->manager->dropIndex($this, $table , $name));
  1426.     }
  1427.  
  1428.     // }}}
  1429.     // {{{ listTableIndexes()
  1430.  
  1431.     /**
  1432.      * list all indexes in a table
  1433.      *
  1434.      * @param string $table name of table that should be used in method
  1435.      * @return mixed data array on success, a MDB error on failure
  1436.      * @access public
  1437.      */
  1438.     function listTableIndexes($table)
  1439.     {
  1440.         $result = $this->loadManager('List table index');
  1441.         if (MDB::isError($result)) {
  1442.             return($result);
  1443.         }
  1444.         return($this->manager->listTableIndexes($this, $table));
  1445.     }
  1446.  
  1447.     // }}}
  1448.     // {{{ getTableIndexDefinition()
  1449.  
  1450.     /**
  1451.      * get the stucture of an index into an array
  1452.      *
  1453.      * @param string $table name of table that should be used in method
  1454.      * @param string $index name of index that should be used in method
  1455.      * @return mixed data array on success, a MDB error on failure
  1456.      * @access public
  1457.      */
  1458.     function getTableIndexDefinition($table, $index)
  1459.     {
  1460.         $result = $this->loadManager('Get table index definition');
  1461.         if (MDB::isError($result)) {
  1462.             return($result);
  1463.         }
  1464.         return($this->manager->getTableIndexDefinition($this, $table, $index));
  1465.     }
  1466.  
  1467.     // }}}
  1468.     // {{{ createSequence()
  1469.  
  1470.     /**
  1471.      * create sequence
  1472.      *
  1473.      * @param string $name name of the sequence to be created
  1474.      * @param string $start start value of the sequence; default is 1
  1475.      * @return mixed MDB_OK on success, a MDB error on failure
  1476.      * @access public
  1477.      */
  1478.     function createSequence($name, $start = 1)
  1479.     {
  1480.         $result = $this->loadManager('Create sequence');
  1481.         if (MDB::isError($result)) {
  1482.             return($result);
  1483.         }
  1484.         return($this->manager->createSequence($this, $name, $start));
  1485.     }
  1486.  
  1487.     // }}}
  1488.     // {{{ dropSequence()
  1489.  
  1490.     /**
  1491.      * drop existing sequence
  1492.      *
  1493.      * @param string $name name of the sequence to be dropped
  1494.      * @return mixed MDB_OK on success, a MDB error on failure
  1495.      * @access public
  1496.      */
  1497.     function dropSequence($name)
  1498.     {
  1499.         $result = $this->loadManager('Drop sequence');
  1500.         if (MDB::isError($result)) {
  1501.             return($result);
  1502.         }
  1503.         return($this->manager->dropSequence($this, $name));
  1504.     }
  1505.  
  1506.     // }}}
  1507.     // {{{ listSequences()
  1508.  
  1509.     /**
  1510.      * list all tables in the current database
  1511.      *
  1512.      * @return mixed data array on success, a MDB error on failure
  1513.      * @access public
  1514.      */
  1515.     function listSequences()
  1516.     {
  1517.         $result = $this->loadManager('List sequences');
  1518.         if (MDB::isError($result)) {
  1519.             return($result);
  1520.         }
  1521.         return($this->manager->listSequences($this));
  1522.     }
  1523.  
  1524.     // }}}
  1525.     // {{{ getSequenceDefinition()
  1526.  
  1527.     /**
  1528.      * get the stucture of a sequence into an array
  1529.      *
  1530.      * @param string $sequence name of sequence that should be used in method
  1531.      * @return mixed data array on success, a MDB error on failure
  1532.      * @access public
  1533.      */
  1534.     function getSequenceDefinition($sequence)
  1535.     {
  1536.         $result = $this->loadManager('Get sequence definition');
  1537.         if (MDB::isError($result)) {
  1538.             return($result);
  1539.         }
  1540.         return($this->manager->getSequenceDefinition($this, $sequence));
  1541.     }
  1542.  
  1543.     // }}}
  1544.     // {{{ query()
  1545.  
  1546.     /**
  1547.      * Send a query to the database and return any results
  1548.      *
  1549.      * @param string $query the SQL query
  1550.      * @param mixed   $types  array that contains the types of the columns in
  1551.      *                        the result set
  1552.      * @return mixed a result handle or MDB_OK on success, a MDB error on failure
  1553.      * @access public
  1554.      */
  1555.     function query($query, $types = NULL)
  1556.     {
  1557.         $this->debug("Query: $query");
  1558.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Query: database queries are not implemented'));
  1559.     }
  1560.  
  1561.     // }}}
  1562.     // {{{ setSelectedRowRange()
  1563.  
  1564.     /**
  1565.      * set the range of the next query
  1566.      *
  1567.      * @param string $first first row to select
  1568.      * @param string $limit number of rows to select
  1569.      * @return mixed MDB_OK on success, a MDB error on failure
  1570.      * @access public
  1571.      */
  1572.     function setSelectedRowRange($first, $limit)
  1573.     {
  1574.         if (!isset($this->supported['SelectRowRanges'])) {
  1575.             return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  1576.                 'Set selected row range: selecting row ranges is not supported by this driver'));
  1577.         }
  1578.         $first = (int)$first;
  1579.         if ($first < 0) {
  1580.             return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
  1581.                 'Set selected row range: it was not specified a valid first selected range row'));
  1582.         }
  1583.         $limit = (int)$limit;
  1584.         if ($limit < 1) {
  1585.             return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
  1586.                 'Set selected row range: it was not specified a valid selected range row limit'));
  1587.         }
  1588.         $this->first_selected_row = $first;
  1589.         $this->selected_row_limit = $limit;
  1590.         return(MDB_OK);
  1591.     }
  1592.  
  1593.     // }}}
  1594.     // {{{ limitQuery()
  1595.  
  1596.     /**
  1597.      * Generates a limited query
  1598.      *
  1599.      * @param string $query query
  1600.      * @param mixed   $types  array that contains the types of the columns in
  1601.      *                        the result set
  1602.      * @param integer $from the row to start to fetching
  1603.      * @param integer $count the numbers of rows to fetch
  1604.      * @return mixed a valid ressource pointer or a MDB_Error
  1605.      * @access public
  1606.      */
  1607.     function limitQuery($query, $types = NULL, $from, $count)
  1608.     {
  1609.         $result = $this->setSelectedRowRange($from, $count);
  1610.         if (MDB::isError($result)) {
  1611.             return($result);
  1612.         }
  1613.         return($this->query($query, $types));
  1614.     }
  1615.  
  1616.     // }}}
  1617.     // {{{ subSelect()
  1618.  
  1619.     /**
  1620.      * simple subselect emulation: leaves the query untouched for all RDBMS
  1621.      * that support subselects
  1622.      *
  1623.      * @access public
  1624.      *
  1625.      * @param string $query the SQL query for the subselect that may only
  1626.      *                      return a column
  1627.      * @param string $quote determines if the data needs to be quoted before
  1628.      *                      being returned
  1629.      *
  1630.      * @return string the query
  1631.      */
  1632.     function subSelect($query, $quote = FALSE)
  1633.     {
  1634.         if ($this->supported['SubSelects'] == 1) {
  1635.             return($query);
  1636.         }
  1637.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Subselect: subselect not implemented'));
  1638.     }
  1639.  
  1640.     // }}}
  1641.     // {{{ replace()
  1642.  
  1643.     /**
  1644.      * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
  1645.      * query, except that if there is already a row in the table with the same
  1646.      * key field values, the REPLACE query just updates its values instead of
  1647.      * inserting a new row.
  1648.      *
  1649.      * The REPLACE type of query does not make part of the SQL standards. Since
  1650.      * pratically only MySQL implements it natively, this type of query is
  1651.      * emulated through this method for other DBMS using standard types of
  1652.      * queries inside a transaction to assure the atomicity of the operation.
  1653.      *
  1654.      * @param string $table name of the table on which the REPLACE query will
  1655.      *       be executed.
  1656.      * @param array $fields associative array that describes the fields and the
  1657.      *       values that will be inserted or updated in the specified table. The
  1658.      *       indexes of the array are the names of all the fields of the table.
  1659.      *       The values of the array are also associative arrays that describe
  1660.      *       the values and other properties of the table fields.
  1661.      *
  1662.      *       Here follows a list of field properties that need to be specified:
  1663.      *
  1664.      *       Value
  1665.      *           Value to be assigned to the specified field. This value may be
  1666.      *           of specified in database independent type format as this
  1667.      *           function can perform the necessary datatype conversions.
  1668.      *
  1669.      *           Default: this property is required unless the Null property is
  1670.      *           set to 1.
  1671.      *
  1672.      *       Type
  1673.      *           Name of the type of the field. Currently, all types Metabase
  1674.      *           are supported except for clob and blob.
  1675.      *
  1676.      *           Default: no type conversion
  1677.      *
  1678.      *       Null
  1679.      *           Boolean property that indicates that the value for this field
  1680.      *           should be set to NULL.
  1681.      *
  1682.      *           The default value for fields missing in INSERT queries may be
  1683.      *           specified the definition of a table. Often, the default value
  1684.      *           is already NULL, but since the REPLACE may be emulated using
  1685.      *           an UPDATE query, make sure that all fields of the table are
  1686.      *           listed in this function argument array.
  1687.      *
  1688.      *           Default: 0
  1689.      *
  1690.      *       Key
  1691.      *           Boolean property that indicates that this field should be
  1692.      *           handled as a primary key or at least as part of the compound
  1693.      *           unique index of the table that will determine the row that will
  1694.      *           updated if it exists or inserted a new row otherwise.
  1695.      *
  1696.      *           This function will fail if no key field is specified or if the
  1697.      *           value of a key field is set to NULL because fields that are
  1698.      *           part of unique index they may not be NULL.
  1699.      *
  1700.      *           Default: 0
  1701.      * @return mixed MDB_OK on success, a MDB error on failure
  1702.      * @access public
  1703.      */
  1704.     function replace($table, $fields)
  1705.     {
  1706.         if (!$this->supported['Replace']) {
  1707.             return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Replace: replace query is not supported'));
  1708.         }
  1709.         $count = count($fields);
  1710.         for($keys = 0, $condition = $insert = $values = '', reset($fields), $field = 0;
  1711.             $field < $count;
  1712.             next($fields), $field++)
  1713.         {
  1714.             $name = key($fields);
  1715.             if ($field > 0) {
  1716.                 $insert .= ', ';
  1717.                 $values .= ', ';
  1718.             }
  1719.             $insert .= $name;
  1720.             if (isset($fields[$name]['Null']) && $fields[$name]['Null']) {
  1721.                 $value = 'NULL';
  1722.             } else {
  1723.                 if(isset($fields[$name]['Type'])) {
  1724.                     switch ($fields[$name]['Type']) {
  1725.                         case 'text':
  1726.                             $value = $this->getTextValue($fields[$name]['Value']);
  1727.                             break;
  1728.                         case 'boolean':
  1729.                             $value = $this->getBooleanValue($fields[$name]['Value']);
  1730.                             break;
  1731.                         case 'integer':
  1732.                             $value = $this->getIntegerValue($fields[$name]['Value']);
  1733.                             break;
  1734.                         case 'decimal':
  1735.                             $value = $this->getDecimalValue($fields[$name]['Value']);
  1736.                             break;
  1737.                         case 'float':
  1738.                             $value = $this->getFloatValue($fields[$name]['Value']);
  1739.                             break;
  1740.                         case 'date':
  1741.                             $value = $this->getDateValue($fields[$name]['Value']);
  1742.                             break;
  1743.                         case 'time':
  1744.                             $value = $this->getTimeValue($fields[$name]['Value']);
  1745.                             break;
  1746.                         case 'timestamp':
  1747.                             $value = $this->getTimestampValue($fields[$name]['Value']);
  1748.                             break;
  1749.                         default:
  1750.                             return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
  1751.                                 'no supported type for field "' . $name . '" specified'));
  1752.                     }
  1753.                 } else {
  1754.                     $value = $fields[$name]['Value'];
  1755.                 }
  1756.             }
  1757.             $values .= $value;
  1758.             if (isset($fields[$name]['Key']) && $fields[$name]['Key']) {
  1759.                 if ($value === 'NULL') {
  1760.                     return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
  1761.                         'key values may not be NULL'));
  1762.                 }
  1763.                 $condition .= ($keys ? ' AND ' : ' WHERE ') . $name . '=' . $value;
  1764.                 $keys++;
  1765.             }
  1766.         }
  1767.         if ($keys == 0) {
  1768.             return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
  1769.                 'not specified which fields are keys'));
  1770.         }
  1771.         $in_transaction = $this->in_transaction;
  1772.         if (!$in_transaction && MDB::isError($result = $this->autoCommit(FALSE))) {
  1773.             return($result);
  1774.         }
  1775.         $success = $this->query("DELETE FROM $table$condition");
  1776.         if (!MDB::isError($success)) {
  1777.             $affected_rows = $this->affected_rows;
  1778.             $success = $this->query("INSERT INTO $table ($insert) VALUES ($values)");
  1779.             $affected_rows += $this->affected_rows;
  1780.         }
  1781.  
  1782.         if (!$in_transaction) {
  1783.             if (!MDB::isError($success)) {
  1784.                 if (!MDB::isError($success = $this->commit())
  1785.                     && !MDB::isError($success = $this->autoCommit(TRUE))
  1786.                     && isset($this->supported['AffectedRows'])
  1787.                 ) {
  1788.                     $this->affected_rows = $affected_rows;
  1789.                 }
  1790.             } else {
  1791.                 $this->rollback();
  1792.                 $this->autoCommit(TRUE);
  1793.             }
  1794.         }
  1795.         return($success);
  1796.     }
  1797.  
  1798.     // }}}
  1799.     // {{{ prepareQuery()
  1800.  
  1801.     /**
  1802.      * Prepares a query for multiple execution with execute().
  1803.      * With some database backends, this is emulated.
  1804.      * prepareQuery() requires a generic query as string like
  1805.      * 'INSERT INTO numbers VALUES(?,?,?)'. The ? are wildcards.
  1806.      * Types of wildcards:
  1807.      *    ? - a quoted scalar value, i.e. strings, integers
  1808.      *
  1809.      * @param string $ the query to prepare
  1810.      * @return mixed resource handle for the prepared query on success, a DB
  1811.      *        error on failure
  1812.      * @access public
  1813.      * @see execute
  1814.      */
  1815.     function prepareQuery($query)
  1816.     {
  1817.         $this->debug("PrepareQuery: $query");
  1818.         $positions = array();
  1819.         for($position = 0;
  1820.             $position < strlen($query) && is_integer($question = strpos($query, '?', $position));
  1821.         ) {
  1822.             if (is_integer($quote = strpos($query, "'", $position))
  1823.                 && $quote < $question
  1824.             ) {
  1825.                 if (!is_integer($end_quote = strpos($query, "'", $quote + 1))) {
  1826.                     return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
  1827.                         'Prepare query: query with an unterminated text string specified'));
  1828.                 }
  1829.                 switch ($this->escape_quotes) {
  1830.                     case '':
  1831.                     case "'":
  1832.                         $position = $end_quote + 1;
  1833.                         break;
  1834.                     default:
  1835.                         if ($end_quote == $quote + 1) {
  1836.                             $position = $end_quote + 1;
  1837.                         } else {
  1838.                             if ($query[$end_quote-1] == $this->escape_quotes) {
  1839.                                 $position = $end_quote;
  1840.                             } else {
  1841.                                 $position = $end_quote + 1;
  1842.                             }
  1843.                         }
  1844.                         break;
  1845.                 }
  1846.             } else {
  1847.                 $positions[] = $question;
  1848.                 $position = $question + 1;
  1849.             }
  1850.         }
  1851.         $this->prepared_queries[] = array(
  1852.             'Query' => $query,
  1853.             'Positions' => $positions,
  1854.             'Values' => array(),
  1855.             'Types' => array()
  1856.             );
  1857.         $prepared_query = count($this->prepared_queries);
  1858.         if ($this->selected_row_limit > 0) {
  1859.             $this->prepared_queries[$prepared_query-1]['First'] = $this->first_selected_row;
  1860.             $this->prepared_queries[$prepared_query-1]['Limit'] = $this->selected_row_limit;
  1861.         }
  1862.         return($prepared_query);
  1863.     }
  1864.  
  1865.     // }}}
  1866.     // {{{ _validatePreparedQuery()
  1867.  
  1868.     /**
  1869.      * validate that a handle is infact a prepared query
  1870.      *
  1871.      * @param int $prepared_query argument is a handle that was returned by
  1872.      *       the function prepareQuery()
  1873.      * @access private
  1874.      */
  1875.     function _validatePreparedQuery($prepared_query)
  1876.     {
  1877.         if ($prepared_query < 1 || $prepared_query > count($this->prepared_queries)) {
  1878.             return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
  1879.                 'Validate prepared query: invalid prepared query'));
  1880.         }
  1881.         if (gettype($this->prepared_queries[$prepared_query-1]) != 'array') {
  1882.             return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
  1883.                 'Validate prepared query: prepared query was already freed'));
  1884.         }
  1885.         return(MDB_OK);
  1886.     }
  1887.  
  1888.     // }}}
  1889.     // {{{ freePreparedQuery()
  1890.  
  1891.     /**
  1892.      * Release resources allocated for the specified prepared query.
  1893.      *
  1894.      * @param int $prepared_query argument is a handle that was returned by
  1895.      *       the function prepareQuery()
  1896.      * @return mixed MDB_OK on success, a MDB error on failure
  1897.      * @access public
  1898.      */
  1899.     function freePreparedQuery($prepared_query)
  1900.     {
  1901.         $result = $this->_validatePreparedQuery($prepared_query);
  1902.         if (MDB::isError($result)) {
  1903.             return($result);
  1904.         }
  1905.         $this->prepared_queries[$prepared_query-1] = '';
  1906.         return(MDB_OK);
  1907.     }
  1908.  
  1909.     // }}}
  1910.     // {{{ _executePreparedQuery()
  1911.  
  1912.     /**
  1913.      * Execute a prepared query statement.
  1914.      *
  1915.      * @param int $prepared_query argument is a handle that was returned by
  1916.      *       the function prepareQuery()
  1917.      * @param string $query query to be executed
  1918.      * @param array $types array that contains the types of the columns in
  1919.      *       the result set
  1920.      * @return mixed a result handle or MDB_OK on success, a MDB error on failure
  1921.      * @access private
  1922.      */
  1923.     function _executePreparedQuery($prepared_query, $query, $types = NULL)
  1924.     {
  1925.         return($this->query($query, $types));
  1926.     }
  1927.  
  1928.     // }}}
  1929.     // {{{ executeQuery()
  1930.  
  1931.     /**
  1932.      * Execute a prepared query statement.
  1933.      *
  1934.      * @param int $prepared_query argument is a handle that was returned by
  1935.      *       the function prepareQuery()
  1936.      * @param array $types array that contains the types of the columns in the
  1937.      *       result set
  1938.      * @return mixed a result handle or MDB_OK on success, a MDB error on failure
  1939.      * @access public
  1940.      */
  1941.     function executeQuery($prepared_query, $types = NULL)
  1942.     {
  1943.         $result = $this->_validatePreparedQuery($prepared_query);
  1944.         if (MDB::isError($result)) {
  1945.             return($result);
  1946.         }
  1947.         $index = $prepared_query-1;
  1948.         $success = MDB_OK;
  1949.         $this->clobs[$prepared_query] = $this->blobs[$prepared_query] = array();
  1950.         $query = '';
  1951.         for($last_position = $position = 0;
  1952.             $position < count($this->prepared_queries[$index]['Positions']);
  1953.             $position++) {
  1954.             if (!isset($this->prepared_queries[$index]['Values'][$position])) {
  1955.                 return($this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL,
  1956.                     'Execute query: it was not defined query argument '.($position + 1)));
  1957.             }
  1958.             $current_position = $this->prepared_queries[$index]['Positions'][$position];
  1959.             $query .= substr($this->prepared_queries[$index]['Query'], $last_position, $current_position - $last_position);
  1960.             $value = $this->prepared_queries[$index]['Values'][$position];
  1961.             if ($this->prepared_queries[$index]['IsNULL'][$position]) {
  1962.                 $query .= $value;
  1963.             } else {
  1964.                 switch ($this->prepared_queries[$index]['Types'][$position]) {
  1965.                     case 'clob':
  1966.                         if (!MDB::isError($success = $this->getClobValue($prepared_query, $position + 1, $value))) {
  1967.                             $this->clobs[$prepared_query][$position + 1] = $success;
  1968.                             $query .= $this->clobs[$prepared_query][$position + 1];
  1969.                         }
  1970.                         break;
  1971.                     case 'blob':
  1972.                         if (!MDB::isError($success = $this->getBlobValue($prepared_query, $position + 1, $value))) {
  1973.                             $this->blobs[$prepared_query][$position + 1] = $success;
  1974.                             $query .= $this->blobs[$prepared_query][$position + 1];
  1975.                         }
  1976.                         break;
  1977.                     default:
  1978.                         $query .= $value;
  1979.                         break;
  1980.                 }
  1981.             }
  1982.             $last_position = $current_position + 1;
  1983.         }
  1984.         if (!MDB::isError($success)) {
  1985.             $query .= substr($this->prepared_queries[$index]['Query'], $last_position);
  1986.             if ($this->selected_row_limit > 0) {
  1987.                 $this->prepared_queries[$index]['First'] = $this->first_selected_row;
  1988.                 $this->prepared_queries[$index]['Limit'] = $this->selected_row_limit;
  1989.             }
  1990.             if (isset($this->prepared_queries[$index]['Limit'])
  1991.                 && $this->prepared_queries[$index]['Limit'] > 0
  1992.             ) {
  1993.                 $this->first_selected_row = $this->prepared_queries[$index]['First'];
  1994.                 $this->selected_row_limit = $this->prepared_queries[$index]['Limit'];
  1995.             } else {
  1996.                 $this->first_selected_row = $this->selected_row_limit = 0;
  1997.             }
  1998.             $success = $this->_executePreparedQuery($prepared_query, $query, $types);
  1999.         }
  2000.         for(reset($this->clobs[$prepared_query]), $clob = 0;
  2001.             $clob < count($this->clobs[$prepared_query]);
  2002.             $clob++, next($this->clobs[$prepared_query])) {
  2003.             $this->freeClobValue($prepared_query, key($this->clobs[$prepared_query]), $this->clobs[$prepared_query][key($this->clobs[$prepared_query])], $success);
  2004.         }
  2005.         unset($this->clobs[$prepared_query]);
  2006.         for(reset($this->blobs[$prepared_query]), $blob = 0;
  2007.             $blob < count($this->blobs[$prepared_query]);
  2008.             $blob++, next($this->blobs[$prepared_query])) {
  2009.             $this->freeBlobValue($prepared_query, key($this->blobs[$prepared_query]), $this->blobs[$prepared_query][key($this->blobs[$prepared_query])], $success);
  2010.         }
  2011.         unset($this->blobs[$prepared_query]);
  2012.         return($success);
  2013.     }
  2014.  
  2015.     // }}}
  2016.     // {{{ execute()
  2017.  
  2018.     /**
  2019.      * Executes a prepared SQL query
  2020.      * With execute() the generic query of prepare is assigned with the given
  2021.      * data array. The values of the array inserted into the query in the same
  2022.      * order like the array order
  2023.      *
  2024.      * @param resource $prepared_query query handle from prepare()
  2025.      * @param array $types array that contains the types of the columns in
  2026.      *        the result set
  2027.      * @param array $params numeric array containing the data to insert into
  2028.      *        the query
  2029.      * @param array $param_types array that contains the types of the values
  2030.      *        defined in $params
  2031.      * @return mixed a new result handle or a MDB_Error when fail
  2032.      * @access public
  2033.      * @see prepare()
  2034.      */
  2035.     function execute($prepared_query, $types = NULL, $params = FALSE, $param_types = NULL)
  2036.     {
  2037.         $this->setParamArray($prepared_query, $params, $param_types);
  2038.  
  2039.         return($this->executeQuery($prepared_query, $types));
  2040.     }
  2041.  
  2042.     // }}}
  2043.     // {{{ executeMultiple()
  2044.  
  2045.     /**
  2046.      * This function does several execute() calls on the same statement handle.
  2047.      * $params must be an array indexed numerically from 0, one execute call is
  2048.      * done for every 'row' in the array.
  2049.      *
  2050.      * If an error occurs during execute(), executeMultiple() does not execute
  2051.      * the unfinished rows, but rather returns that error.
  2052.      *
  2053.      * @param resource $stmt query handle from prepare()
  2054.      * @param array $types array that contains the types of the columns in
  2055.      *        the result set
  2056.      * @param array $params numeric array containing the
  2057.      *        data to insert into the query
  2058.      * @param array $parAM_types array that contains the types of the values
  2059.      *        defined in $params
  2060.      * @return mixed a result handle or MDB_OK on success, a MDB error on failure
  2061.      * @access public
  2062.      * @see prepare(), execute()
  2063.      */
  2064.     function executeMultiple($prepared_query, $types = NULL, $params, $param_types = NULL)
  2065.     {
  2066.         for($i = 0, $j = count($params); $i < $j; $i++) {
  2067.             $result = $this->execute($prepared_query, $types, $params[$i], $param_types);
  2068.             if (MDB::isError($result)) {
  2069.                 return($result);
  2070.             }
  2071.         }
  2072.         return(MDB_OK);
  2073.     }
  2074.  
  2075.     // }}}
  2076.     // {{{ setParam()
  2077.  
  2078.     /**
  2079.      * Set the value of a parameter of a prepared query.
  2080.      *
  2081.      * @param int $prepared_query argument is a handle that was returned
  2082.      *       by the function prepareQuery()
  2083.      * @param int $parameter the order number of the parameter in the query
  2084.      *       statement. The order number of the first parameter is 1.
  2085.      * @param string $type designation of the type of the parameter to be set.
  2086.      *       The designation of the currently supported types is as follows:
  2087.      *           text, boolean, integer, decimal, float, date, time, timestamp,
  2088.      *           clob, blob
  2089.      * @param mixed $value value that is meant to be assigned to specified
  2090.      *       parameter. The type of the value depends on the $type argument.
  2091.      * @param boolean $is_null flag that indicates whether whether the
  2092.      *       parameter is a NULL
  2093.      * @param string $field name of the field that is meant to be assigned
  2094.      *       with this parameter value when it is of type clob or blob
  2095.      * @return mixed MDB_OK on success, a MDB error on failure
  2096.      * @access public
  2097.      */
  2098.     function setParam($prepared_query, $parameter, $type, $value, $is_null = 0, $field = '')
  2099.     {
  2100.         $result = $this->_validatePreparedQuery($prepared_query);
  2101.         if (MDB::isError($result)) {
  2102.             return($result);
  2103.         }
  2104.         $index = $prepared_query - 1;
  2105.         if ($parameter < 1 || $parameter > count($this->prepared_queries[$index]['Positions'])) {
  2106.             return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
  2107.                 'Query set: it was not specified a valid argument number'));
  2108.         }
  2109.         $this->prepared_queries[$index]['Values'][$parameter-1] = $value;
  2110.         $this->prepared_queries[$index]['Types'][$parameter-1] = $type;
  2111.         $this->prepared_queries[$index]['Fields'][$parameter-1] = $field;
  2112.         $this->prepared_queries[$index]['IsNULL'][$parameter-1] = $is_null;
  2113.         return(MDB_OK);
  2114.     }
  2115.  
  2116.     // }}}
  2117.     // {{{ setParamArray()
  2118.  
  2119.     /**
  2120.      * Set the values of multiple a parameter of a prepared query in bulk.
  2121.      *
  2122.      * @param int $prepared_query argument is a handle that was returned by
  2123.      *       the function prepareQuery()
  2124.      * @param array $params array thats specifies all necessary infromation
  2125.      *       for setParam() the array elements must use keys corresponding to
  2126.      *       the number of the position of the parameter.
  2127.      * @param array $types array thats specifies the types of the fields
  2128.      * @return mixed MDB_OK on success, a MDB error on failure
  2129.      * @access public
  2130.      * @see setParam()
  2131.      */
  2132.     function setParamArray($prepared_query, $params, $types = NULL)
  2133.     {
  2134.         if (is_array($types)) {
  2135.             if (count($params) != count($types)) {
  2136.                 return $this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
  2137.                     'setParamArray: the number of given types ('.count($types).')'
  2138.                     .'is not corresponding to the number of given parameters ('.count($params).')');
  2139.             }
  2140.             for($i = 0, $j = count($params); $i < $j; ++$i) {
  2141.                 switch ($types[$i]) {
  2142.                     case 'NULL':
  2143.                         $success = $this->setParam($prepared_query, $i + 1, $params[$i][0], 'NULL', 1, '');
  2144.                         break;
  2145.                     case 'text':
  2146.                         $success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i]));
  2147.                         break;
  2148.                     case 'clob':
  2149.                         $success = $this->setParam($prepared_query, $i + 1, 'clob', $params[$i][0], 0, $params[$i][1]);
  2150.                         break;
  2151.                     case 'blob':
  2152.                         $success = $this->setParam($prepared_query, $i + 1, 'blob', $params[$i][0], 0, $params[$i][1]);
  2153.                         break;
  2154.                     case 'integer':
  2155.                         $success = $this->setParam($prepared_query, $i + 1, 'integer', $this->getIntegerValue($params[$i]));
  2156.                         break;
  2157.                     case 'boolean':
  2158.                         $success = $this->setParam($prepared_query, $i + 1, 'boolean', $this->getBooleanValue($params[$i]));
  2159.                         break;
  2160.                     case 'date':
  2161.                         $success = $this->setParam($prepared_query, $i + 1, 'date', $this->getDateValue($params[$i]));
  2162.                         break;
  2163.                     case 'timestamp':
  2164.                         $success = $this->setParam($prepared_query, $i + 1, 'timestamp', $this->getTimestampValue($params[$i]));
  2165.                         break;
  2166.                     case 'time':
  2167.                         $success = $this->setParam($prepared_query, $i + 1, 'time', $this->getTimeValue($params[$i]));
  2168.                         break;
  2169.                     case 'float':
  2170.                         $success = $this->setParam($prepared_query, $i + 1, 'float', $this->getFloatValue($params[$i]));
  2171.                         break;
  2172.                     case 'decimal':
  2173.                         $success = $this->setParam($prepared_query, $i + 1, 'decimal', $this->getDecimalValue($params[$i]));
  2174.                         break;
  2175.                     default:
  2176.                         $success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i]));
  2177.                         break;
  2178.                 }
  2179.                 if (MDB::isError($success)) {
  2180.                     return($success);
  2181.                 }
  2182.             }
  2183.         } else {
  2184.             for($i = 0, $j = count($params); $i < $j; ++$i) {
  2185.                 $success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i]));
  2186.                 if (MDB::isError($success)) {
  2187.                     return($success);
  2188.                 }
  2189.             }
  2190.         }
  2191.         return(MDB_OK);
  2192.     }
  2193.  
  2194.     // }}}
  2195.     // {{{ setParamNull()
  2196.  
  2197.     /**
  2198.      * Set the value of a parameter of a prepared query to NULL.
  2199.      *
  2200.      * @param int $prepared_query argument is a handle that was returned by
  2201.      *       the function prepareQuery()
  2202.      * @param int $parameter order number of the parameter in the query
  2203.      *       statement. The order number of the first parameter is 1.
  2204.      * @param string $type designation of the type of the parameter to be set.
  2205.      *       The designation of the currently supported types is list in the
  2206.      *       usage of the function  setParam()
  2207.      * @return mixed MDB_OK on success, a MDB error on failure
  2208.      * @access public
  2209.      * @see setParam()
  2210.      */
  2211.     function setParamNull($prepared_query, $parameter, $type)
  2212.     {
  2213.         return($this->setParam($prepared_query, $parameter, $type, 'NULL', 1, ''));
  2214.     }
  2215.  
  2216.     // }}}
  2217.     // {{{ setParamText()
  2218.  
  2219.     /**
  2220.      * Set a parameter of a prepared query with a text value.
  2221.      *
  2222.      * @param int $prepared_query argument is a handle that was returned by
  2223.      *       the function prepareQuery()
  2224.      * @param int $parameter order number of the parameter in the query
  2225.      *       statement. The order number of the first parameter is 1.
  2226.      * @param string $value text value that is meant to be assigned to
  2227.      *       specified parameter.
  2228.      * @return mixed MDB_OK on success, a MDB error on failure
  2229.      * @access public
  2230.      * @see setParam()
  2231.      */
  2232.     function setParamText($prepared_query, $parameter, $value)
  2233.     {
  2234.         return($this->setParam($prepared_query, $parameter, 'text', $this->getTextValue($value)));
  2235.     }
  2236.  
  2237.     // }}}
  2238.     // {{{ setParamClob()
  2239.  
  2240.     /**
  2241.      * Set a parameter of a prepared query with a character large object value.
  2242.      *
  2243.      * @param int $prepared_query argument is a handle that was returned by
  2244.      *       the function prepareQuery()
  2245.      * @param int $parameter order number of the parameter in the query
  2246.      *       statement. The order number of the first parameter is 1.
  2247.      * @param int $value handle of large object created with createLOB()
  2248.      *       function from which it will be read the data value that is meant
  2249.      *       to be assigned to specified parameter.
  2250.      * @param string $field name of the field of a INSERT or UPDATE query to
  2251.      *       which it will be assigned the value to specified parameter.
  2252.      * @return mixed MDB_OK on success, a MDB error on failure
  2253.      * @access public
  2254.      * @see setParam()
  2255.      */
  2256.     function setParamClob($prepared_query, $parameter, $value, $field)
  2257.     {
  2258.         return($this->setParam($prepared_query, $parameter, 'clob', $value, 0, $field));
  2259.     }
  2260.  
  2261.     // }}}
  2262.     // {{{ setParamBlob()
  2263.  
  2264.     /**
  2265.      * Set a parameter of a prepared query with a binary large object value.
  2266.      *
  2267.      * @param int $prepared_query argument is a handle that was returned by
  2268.      *       the function prepareQuery()
  2269.      * @param int $parameter order number of the parameter in the query
  2270.      *       statement. The order number of the first parameter is 1.
  2271.      * @param int $value handle of large object created with createLOB()
  2272.      *       function from which it will be read the data value that is meant
  2273.      *       to be assigned to specified parameter.
  2274.      * @param string $field name of the field of a INSERT or UPDATE query to
  2275.      *       which it will be assigned the value to specified parameter.
  2276.      * @return mixed MDB_OK on success, a MDB error on failure
  2277.      * @access public
  2278.      * @see setParam()
  2279.      */
  2280.     function setParamBlob($prepared_query, $parameter, $value, $field)
  2281.     {
  2282.         return($this->setParam($prepared_query, $parameter, 'blob', $value, 0, $field));
  2283.     }
  2284.  
  2285.     // }}}
  2286.     // {{{ setParamInteger()
  2287.  
  2288.     /**
  2289.      * Set a parameter of a prepared query with a text value.
  2290.      *
  2291.      * @param int $prepared_query argument is a handle that was returned by
  2292.      *       the function prepareQuery()
  2293.      * @param int $parameter order number of the parameter in the query
  2294.      *       statement. The order number of the first parameter is 1.
  2295.      * @param int $value an integer value that is meant to be assigned to
  2296.      *       specified parameter.
  2297.      * @return mixed MDB_OK on success, a MDB error on failure
  2298.      * @access public
  2299.      * @see setParam()
  2300.      */
  2301.     function setParamInteger($prepared_query, $parameter, $value)
  2302.     {
  2303.         return($this->setParam($prepared_query, $parameter, 'integer', $this->getIntegerValue($value)));
  2304.     }
  2305.  
  2306.     // }}}
  2307.     // {{{ setParamBoolean()
  2308.  
  2309.     /**
  2310.      * Set a parameter of a prepared query with a boolean value.
  2311.      *
  2312.      * @param int $prepared_query argument is a handle that was returned by
  2313.      *       the function prepareQuery()
  2314.      * @param int $parameter order number of the parameter in the query
  2315.      *       statement. The order number of the first parameter is 1.
  2316.      * @param boolean $value boolean value that is meant to be assigned to
  2317.      *       specified parameter.
  2318.      * @return mixed MDB_OK on success, a MDB error on failure
  2319.      * @access public
  2320.      * @see setParam()
  2321.      */
  2322.     function setParamBoolean($prepared_query, $parameter, $value)
  2323.     {
  2324.         return($this->setParam($prepared_query, $parameter, 'boolean', $this->getBooleanValue($value)));
  2325.     }
  2326.  
  2327.     // }}}
  2328.     // {{{ setParamDate()
  2329.  
  2330.     /**
  2331.      * Set a parameter of a prepared query with a date value.
  2332.      *
  2333.      * @param int $prepared_query argument is a handle that was returned by
  2334.      *       the function prepareQuery()
  2335.      * @param int $parameter order number of the parameter in the query
  2336.      *       statement. The order number of the first parameter is 1.
  2337.      * @param string $value date value that is meant to be assigned to
  2338.      *       specified parameter.
  2339.      * @return mixed MDB_OK on success, a MDB error on failure
  2340.      * @access public
  2341.      * @see setParam()
  2342.      */
  2343.     function setParamDate($prepared_query, $parameter, $value)
  2344.     {
  2345.         return($this->setParam($prepared_query, $parameter, 'date', $this->getDateValue($value)));
  2346.     }
  2347.  
  2348.     // }}}
  2349.     // {{{ setParamTimestamp()
  2350.  
  2351.     /**
  2352.      * Set a parameter of a prepared query with a time stamp value.
  2353.      *
  2354.      * @param int $prepared_query argument is a handle that was returned by
  2355.      *       the function prepareQuery()
  2356.      * @param int $parameter order number of the parameter in the query
  2357.      *       statement. The order number of the first parameter is 1.
  2358.      * @param string $value time stamp value that is meant to be assigned to
  2359.      *       specified parameter.
  2360.      * @return mixed MDB_OK on success, a MDB error on failure
  2361.      * @access public
  2362.      * @see setParam()
  2363.      */
  2364.     function setParamTimestamp($prepared_query, $parameter, $value)
  2365.     {
  2366.         return($this->setParam($prepared_query, $parameter, 'timestamp', $this->getTimestampValue($value)));
  2367.     }
  2368.  
  2369.     // }}}
  2370.     // {{{ setParamTime()
  2371.  
  2372.     /**
  2373.      * Set a parameter of a prepared query with a time value.
  2374.      *
  2375.      * @param int $prepared_query argument is a handle that was returned by
  2376.      *       the function prepareQuery()
  2377.      * @param int $parameter order number of the parameter in the query
  2378.      *       statement. The order number of the first parameter is 1.
  2379.      * @param string $value time value that is meant to be assigned to
  2380.      *       specified parameter.
  2381.      * @return mixed MDB_OK on success, a MDB error on failure
  2382.      * @access public
  2383.      * @see setParam()
  2384.      */
  2385.     function setParamTime($prepared_query, $parameter, $value)
  2386.     {
  2387.         return($this->setParam($prepared_query, $parameter, 'time', $this->getTimeValue($value)));
  2388.     }
  2389.  
  2390.     // }}}
  2391.     // {{{ setParamFloat()
  2392.  
  2393.     /**
  2394.      * Set a parameter of a prepared query with a float value.
  2395.      *
  2396.      * @param int $prepared_query argument is a handle that was returned by
  2397.      *       the function prepareQuery()
  2398.      * @param int $parameter order number of the parameter in the query
  2399.      *       statement. The order number of the first parameter is 1.
  2400.      * @param string $value float value that is meant to be assigned to
  2401.      *       specified parameter.
  2402.      * @return mixed MDB_OK on success, a MDB error on failure
  2403.      * @access public
  2404.      * @see setParam()
  2405.      */
  2406.     function setParamFloat($prepared_query, $parameter, $value)
  2407.     {
  2408.         return($this->setParam($prepared_query, $parameter, 'float', $this->getFloatValue($value)));
  2409.     }
  2410.  
  2411.     // }}}
  2412.     // {{{ setParamDecimal()
  2413.  
  2414.     /**
  2415.      * Set a parameter of a prepared query with a decimal value.
  2416.      *
  2417.      * @param int $prepared_query argument is a handle that was returned by
  2418.      *       the function prepareQuery()
  2419.      * @param int $parameter order number of the parameter in the query
  2420.      *       statement. The order number of the first parameter is 1.
  2421.      * @param string $value decimal value that is meant to be assigned to
  2422.      *       specified parameter.
  2423.      * @return mixed MDB_OK on success, a MDB error on failure
  2424.      * @access public
  2425.      * @see setParam()
  2426.      */
  2427.     function setParamDecimal($prepared_query, $parameter, $value)
  2428.     {
  2429.         return($this->setParam($prepared_query, $parameter, 'decimal', $this->getDecimalValue($value)));
  2430.     }
  2431.  
  2432.     // }}}
  2433.     // {{{ setResultTypes()
  2434.  
  2435.     /**
  2436.      * Define the list of types to be associated with the columns of a given
  2437.      * result set.
  2438.      *
  2439.      * This function may be called before invoking fetchInto(), fetchOne(),
  2440.      * fetchRow(), fetchCol() and fetchAll() so that the necessary data type
  2441.      * conversions are performed on the data to be retrieved by them. If this
  2442.      * function is not called, the type of all result set columns is assumed
  2443.      * to be text, thus leading to not perform any conversions.
  2444.      *
  2445.      * @param resource $result result identifier
  2446.      * @param string $types array variable that lists the
  2447.      *       data types to be expected in the result set columns. If this array
  2448.      *       contains less types than the number of columns that are returned
  2449.      *       in the result set, the remaining columns are assumed to be of the
  2450.      *       type text. Currently, the types clob and blob are not fully
  2451.      *       supported.
  2452.      * @return mixed MDB_OK on success, a MDB error on failure
  2453.      * @access public
  2454.      */
  2455.     function setResultTypes($result, $types)
  2456.     {
  2457.         $result_value = intval($result);
  2458.         if (isset($this->result_types[$result_value])) {
  2459.             return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
  2460.                 'Set result types: attempted to redefine the types of the columns of a result set'));
  2461.         }
  2462.         $columns = $this->numCols($result);
  2463.         if (MDB::isError($columns)) {
  2464.             return($columns);
  2465.         }
  2466.         if ($columns < count($types)) {
  2467.             return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
  2468.                 'Set result types: it were specified more result types (' . count($types) . ') than result columns (' . $columns . ')'));
  2469.         }
  2470.         $valid_types = array(
  2471.             'text'      => MDB_TYPE_TEXT,
  2472.             'boolean'   => MDB_TYPE_BOOLEAN,
  2473.             'integer'   => MDB_TYPE_INTEGER,
  2474.             'decimal'   => MDB_TYPE_DECIMAL,
  2475.             'float'     => MDB_TYPE_FLOAT,
  2476.             'date'      => MDB_TYPE_DATE,
  2477.             'time'      => MDB_TYPE_TIME,
  2478.             'timestamp' => MDB_TYPE_TIMESTAMP,
  2479.             'clob'      => MDB_TYPE_CLOB,
  2480.             'blob'      => MDB_TYPE_BLOB
  2481.         );
  2482.         for($column = 0; $column < count($types); $column++) {
  2483.             if (!isset($valid_types[$types[$column]])) {
  2484.                 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  2485.                     'Set result types: ' . $types[$column] . ' is not a supported column type'));
  2486.             }
  2487.             $this->result_types[$result_value][$column] = $valid_types[$types[$column]];
  2488.         }
  2489.         while ($column < $columns) {
  2490.             $this->result_types[$result_value][$column] = MDB_TYPE_TEXT;
  2491.             $column++;
  2492.         }
  2493.         return(MDB_OK);
  2494.     }
  2495.  
  2496.     // }}}
  2497.     // {{{ affectedRows()
  2498.  
  2499.     /**
  2500.      * returns the affected rows of a query
  2501.      *
  2502.      * @return mixed MDB_Error or number of rows
  2503.      * @access public
  2504.      */
  2505.     function affectedRows()
  2506.     {
  2507.         if ($this->affected_rows == -1) {
  2508.             return($this->raiseError(MDB_ERROR_NEED_MORE_DATA));
  2509.         }
  2510.         return($this->affected_rows);
  2511.     }
  2512.  
  2513.     // }}}
  2514.     // {{{ getColumnNames()
  2515.  
  2516.     /**
  2517.      * Retrieve the names of columns returned by the DBMS in a query result.
  2518.      *
  2519.      * @param resource $result result identifier
  2520.      * @return mixed associative array variable
  2521.      *       that holds the names of columns. The indexes of the array are
  2522.      *       the column names mapped to lower case and the values are the
  2523.      *       respective numbers of the columns starting from 0. Some DBMS may
  2524.      *       not return any columns when the result set does not contain any
  2525.      *       rows.
  2526.      *      a MDB error on failure
  2527.      * @access public
  2528.      */
  2529.     function getColumnNames($result)
  2530.     {
  2531.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  2532.             'Get column names: obtaining result column names is not implemented'));
  2533.     }
  2534.  
  2535.     // }}}
  2536.     // {{{ numCols()
  2537.  
  2538.     /**
  2539.      * Count the number of columns returned by the DBMS in a query result.
  2540.      *
  2541.      * @param resource $result result identifier
  2542.      * @return mixed integer value with the number of columns, a MDB error
  2543.      *       on failure
  2544.      * @access public
  2545.      */
  2546.     function numCols($result)
  2547.     {
  2548.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  2549.             'Number of columns: obtaining the number of result columns is not implemented'));
  2550.     }
  2551.  
  2552.     // }}}
  2553.     // {{{ endOfResult()
  2554.  
  2555.     /**
  2556.      * check if the end of the result set has been reached
  2557.      *
  2558.      * @param resource $result result identifier
  2559.      * @return mixed TRUE or FALSE on sucess, a MDB error on failure
  2560.      * @access public
  2561.      */
  2562.     function endOfResult($result)
  2563.     {
  2564.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  2565.             'End of result: end of result method not implemented'));
  2566.     }
  2567.  
  2568.     // }}}
  2569.     // {{{ setFetchMode()
  2570.  
  2571.     /**
  2572.      * Sets which fetch mode should be used by default on queries
  2573.      * on this connection.
  2574.      *
  2575.      * @param integer $fetchmode MDB_FETCHMODE_ORDERED or MDB_FETCHMODE_ASSOC,
  2576.      *       possibly bit-wise OR'ed with MDB_FETCHMODE_FLIPPED.
  2577.      * @access public
  2578.      * @see MDB_FETCHMODE_ORDERED
  2579.      * @see MDB_FETCHMODE_ASSOC
  2580.      * @see MDB_FETCHMODE_FLIPPED
  2581.      */
  2582.     function setFetchMode($fetchmode)
  2583.     {
  2584.         switch ($fetchmode) {
  2585.             case MDB_FETCHMODE_ORDERED:
  2586.             case MDB_FETCHMODE_ASSOC:
  2587.                 $this->fetchmode = $fetchmode;
  2588.                 break;
  2589.             default:
  2590.                 return($this->raiseError('invalid fetchmode mode'));
  2591.         }
  2592.     }
  2593.  
  2594.     // }}}
  2595.     // {{{ fetch()
  2596.  
  2597.     /**
  2598.      * fetch value from a result set
  2599.      *
  2600.      * @param resource $result result identifier
  2601.      * @param int $row number of the row where the data can be found
  2602.      * @param int $field field number where the data can be found
  2603.      * @return mixed string on success, a MDB error on failure
  2604.      * @access public
  2605.      */
  2606.     function fetch($result, $row, $field)
  2607.     {
  2608.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  2609.             'Fetch: fetch result method not implemented'));
  2610.     }
  2611.  
  2612.     // }}}
  2613.     // {{{ fetchLob()
  2614.  
  2615.     /**
  2616.      * fetch a lob value from a result set
  2617.      *
  2618.      * @param resource $result result identifier
  2619.      * @param int $row number of the row where the data can be found
  2620.      * @param int $field field number where the data can be found
  2621.      * @return mixed string on success, a MDB error on failure
  2622.      * @access public
  2623.      */
  2624.     function fetchLob($result, $row, $field)
  2625.     {
  2626.         $lob = count($this->lobs) + 1;
  2627.         $this->lobs[$lob] = array(
  2628.             'Result' => $result,
  2629.             'Row' => $row,
  2630.             'Field' => $field,
  2631.             'Position' => 0
  2632.         );
  2633.         $dst_lob = array(
  2634.             'Database' => $this,
  2635.             'Error' => '',
  2636.             'Type' => 'resultlob',
  2637.             'ResultLOB' => $lob
  2638.         );
  2639.         if (MDB::isError($lob = $this->createLob($dst_lob))) {
  2640.             return($this->raiseError(MDB_ERROR, NULL, NULL,
  2641.                 'Fetch LOB result: ' . $dst_lob['Error']));
  2642.         }
  2643.         return($lob);
  2644.     }
  2645.  
  2646.     // }}}
  2647.     // {{{ _retrieveLob()
  2648.  
  2649.     /**
  2650.      * fetch a float value from a result set
  2651.      *
  2652.      * @param int $lob handle to a lob created by the createLob() function
  2653.      * @return mixed MDB_OK on success, a MDB error on failure
  2654.      * @access private
  2655.      */
  2656.     function _retrieveLob($lob)
  2657.     {
  2658.         if (!isset($this->lobs[$lob])) {
  2659.             return($this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL,
  2660.                 'Fetch LOB result: it was not specified a valid lob'));
  2661.         }
  2662.         if (!isset($this->lobs[$lob]['Value'])) {
  2663.             $this->lobs[$lob]['Value'] = $this->fetch($this->lobs[$lob]['Result'], $this->lobs[$lob]['Row'], $this->lobs[$lob]['Field']);
  2664.         }
  2665.         return(MDB_OK);
  2666.     }
  2667.  
  2668.     // }}}
  2669.     // {{{ endOfResultLob()
  2670.  
  2671.     /**
  2672.      * Determine whether it was reached the end of the large object and
  2673.      * therefore there is no more data to be read for the its input stream.
  2674.      *
  2675.      * @param int $lob handle to a lob created by the createLob() function
  2676.      * @return mixed TRUE or FALSE on success, a MDB error on failure
  2677.      * @access public
  2678.      */
  2679.     function endOfResultLob($lob)
  2680.     {
  2681.         $result = $this->_retrieveLob($lob);
  2682.         if (MDB::isError($result)) {
  2683.             return($result);
  2684.         }
  2685.         return($this->lobs[$lob]['Position'] >= strlen($this->lobs[$lob]['Value']));
  2686.     }
  2687.  
  2688.     // }}}
  2689.     // {{{ _readResultLob()
  2690.  
  2691.     /**
  2692.      * Read data from large object input stream.
  2693.      *
  2694.      * @param int $lob handle to a lob created by the createLob() function
  2695.      * @param blob $data reference to a variable that will hold data to be
  2696.      *       read from the large object input stream
  2697.      * @param int $length integer value that indicates the largest ammount of
  2698.      *       data to be read from the large object input stream.
  2699.      * @return mixed length on success, a MDB error on failure
  2700.      * @access private
  2701.      */
  2702.     function _readResultLob($lob, &$data, $length)
  2703.     {
  2704.         $result = $this->_retrieveLob($lob);
  2705.         if (MDB::isError($result)) {
  2706.             return($result);
  2707.         }
  2708.         $length = min($length, strlen($this->lobs[$lob]['Value']) - $this->lobs[$lob]['Position']);
  2709.         $data = substr($this->lobs[$lob]['Value'], $this->lobs[$lob]['Position'], $length);
  2710.         $this->lobs[$lob]['Position'] += $length;
  2711.         return($length);
  2712.     }
  2713.  
  2714.     // }}}
  2715.     // {{{ _destroyResultLob()
  2716.  
  2717.     /**
  2718.      * Free any resources allocated during the lifetime of the large object
  2719.      * handler object.
  2720.      *
  2721.      * @param int $lob handle to a lob created by the createLob() function
  2722.      * @access private
  2723.      */
  2724.     function _destroyResultLob($lob)
  2725.     {
  2726.         if (isset($this->lobs[$lob])) {
  2727.             $this->lobs[$lob] = '';
  2728.         }
  2729.     }
  2730.  
  2731.     // }}}
  2732.     // {{{ fetchClob()
  2733.  
  2734.     /**
  2735.      * fetch a clob value from a result set
  2736.      *
  2737.      * @param resource $result result identifier
  2738.      * @param int $row number of the row where the data can be found
  2739.      * @param int $field field number where the data can be found
  2740.      * @return mixed content of the specified data cell, a MDB error on failure,
  2741.      *        a MDB error on failure
  2742.      * @access public
  2743.      */
  2744.     function fetchClob($result, $row, $field)
  2745.     {
  2746.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  2747.             'fetch clob result method is not implemented'));
  2748.     }
  2749.  
  2750.     // }}}
  2751.     // {{{ fetchBlob()
  2752.  
  2753.     /**
  2754.      * fetch a blob value from a result set
  2755.      *
  2756.      * @param resource $result result identifier
  2757.      * @param int $row number of the row where the data can be found
  2758.      * @param int $field field number where the data can be found
  2759.      * @return mixed content of the specified data cell, a MDB error on failure
  2760.      * @access public
  2761.      */
  2762.     function fetchBlob($result, $row, $field)
  2763.     {
  2764.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  2765.             'fetch blob result method is not implemented'));
  2766.     }
  2767.  
  2768.     // }}}
  2769.     // {{{ resultIsNull()
  2770.  
  2771.     /**
  2772.      * Determine whether the value of a query result located in given row and
  2773.      *    field is a NULL.
  2774.      *
  2775.      * @param resource $result result identifier
  2776.      * @param int $row number of the row where the data can be found
  2777.      * @param int $field field number where the data can be found
  2778.      * @return mixed TRUE or FALSE on success, a MDB error on failure
  2779.      * @access public
  2780.      */
  2781.     function resultIsNull($result, $row, $field)
  2782.     {
  2783.         $result = $this->fetch($result, $row, $field);
  2784.         if (MDB::isError($result)) {
  2785.             return($result);
  2786.         }
  2787.         return(!isset($result));
  2788.     }
  2789.  
  2790.     // }}}
  2791.     // {{{ _baseConvertResult()
  2792.  
  2793.     /**
  2794.      * general type conversion method
  2795.      *
  2796.      * @param mixed $value refernce to a value to be converted
  2797.      * @param int $type constant that specifies which type to convert to
  2798.      * @return object a MDB error on failure
  2799.      * @access private
  2800.      */
  2801.     function _baseConvertResult($value, $type)
  2802.     {
  2803.         switch ($type) {
  2804.             case MDB_TYPE_TEXT:
  2805.                 return($value);
  2806.             case MDB_TYPE_BLOB:
  2807.                 return($value);
  2808.             case MDB_TYPE_CLOB:
  2809.                 return($value);
  2810.             case MDB_TYPE_INTEGER:
  2811.                 return(intval($value));
  2812.             case MDB_TYPE_BOOLEAN:
  2813.                 return ($value == 'Y') ? TRUE : FALSE;
  2814.             case MDB_TYPE_DECIMAL:
  2815.                 return($value);
  2816.             case MDB_TYPE_FLOAT:
  2817.                 return(doubleval($value));
  2818.             case MDB_TYPE_DATE:
  2819.                 return($value);
  2820.             case MDB_TYPE_TIME:
  2821.                 return($value);
  2822.             case MDB_TYPE_TIMESTAMP:
  2823.                 return($value);
  2824.             case MDB_TYPE_CLOB:
  2825.                 return($value);
  2826.             case MDB_TYPE_BLOB:
  2827.                 return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
  2828.                     'BaseConvertResult: attempt to convert result value to an unsupported type ' . $type));
  2829.             default:
  2830.                 return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
  2831.                     'BaseConvertResult: attempt to convert result value to an unknown type ' . $type));
  2832.         }
  2833.     }
  2834.  
  2835.     // }}}
  2836.     // {{{ convertResult()
  2837.  
  2838.     /**
  2839.      * convert a value to a RDBMS indepdenant MDB type
  2840.      *
  2841.      * @param mixed $value value to be converted
  2842.      * @param int $type constant that specifies which type to convert to
  2843.      * @return mixed converted value or a MDB error on failure
  2844.      * @access public
  2845.      */
  2846.     function convertResult($value, $type)
  2847.     {
  2848.         return($this->_baseConvertResult($value, $type));
  2849.     }
  2850.  
  2851.     // }}}
  2852.     // {{{ convertResultRow()
  2853.  
  2854.     /**
  2855.      * convert a result row
  2856.      *
  2857.      * @param resource $result result identifier
  2858.      * @param array $row array with data
  2859.      * @return mixed MDB_OK on success,  a MDB error on failure
  2860.      * @access public
  2861.      */
  2862.     function convertResultRow($result, $row)
  2863.     {
  2864.         $result_value = intval($result);
  2865.         if (isset($this->result_types[$result_value])) {
  2866.             $current_column = -1;
  2867.             foreach($row as $key => $column) {
  2868.                 ++$current_column;
  2869.                 if (!isset($this->result_types[$result_value][$current_column])
  2870.                    ||!isset($column)
  2871.                 ) {
  2872.                     continue;
  2873.                 }
  2874.                 switch ($type = $this->result_types[$result_value][$current_column]) {
  2875.                     case MDB_TYPE_TEXT:
  2876.                     case MDB_TYPE_BLOB:
  2877.                     case MDB_TYPE_CLOB:
  2878.                         break;
  2879.                     case MDB_TYPE_INTEGER:
  2880.                         $row[$key] = intval($row[$key]);
  2881.                         break;
  2882.                     default:
  2883.                         $value = $this->convertResult($row[$key], $type);
  2884.                         if (MDB::isError($value)) {
  2885.                             return $value;
  2886.                         }
  2887.                         $row[$key] = $value;
  2888.                         break;
  2889.                 }
  2890.             }
  2891.         }
  2892.         return ($row);
  2893.     }
  2894.  
  2895.     // }}}
  2896.     // {{{ fetchDate()
  2897.  
  2898.     /**
  2899.      * fetch a date value from a result set
  2900.      *
  2901.      * @param resource $result result identifier
  2902.      * @param int $row number of the row where the data can be found
  2903.      * @param int $field field number where the data can be found
  2904.      * @return mixed content of the specified data cell, a MDB error on failure
  2905.      * @access public
  2906.      */
  2907.     function fetchDate($result, $row, $field)
  2908.     {
  2909.         $value = $this->fetch($result, $row, $field);
  2910.         return($this->convertResult($value, MDB_TYPE_DATE));
  2911.     }
  2912.  
  2913.     // }}}
  2914.     // {{{ fetchTimestamp()
  2915.  
  2916.     /**
  2917.      * fetch a timestamp value from a result set
  2918.      *
  2919.      * @param resource $result result identifier
  2920.      * @param int $row number of the row where the data can be found
  2921.      * @param int $field field number where the data can be found
  2922.      * @return mixed content of the specified data cell, a MDB error on failure
  2923.      * @access public
  2924.      */
  2925.     function fetchTimestamp($result, $row, $field)
  2926.     {
  2927.         $value = $this->fetch($result, $row, $field);
  2928.         return($this->convertResult($value, MDB_TYPE_TIMESTAMP));
  2929.     }
  2930.  
  2931.     // }}}
  2932.     // {{{ fetchTime()
  2933.  
  2934.     /**
  2935.      * fetch a time value from a result set
  2936.      *
  2937.      * @param resource $result result identifier
  2938.      * @param int $row number of the row where the data can be found
  2939.      * @param int $field field number where the data can be found
  2940.      * @return mixed content of the specified data cell, a MDB error on failure
  2941.      * @access public
  2942.      */
  2943.     function fetchTime($result, $row, $field)
  2944.     {
  2945.         $value = $this->fetch($result, $row, $field);
  2946.         return($this->convertResult($value, MDB_TYPE_TIME));
  2947.     }
  2948.  
  2949.     // }}}
  2950.     // {{{ fetchBoolean()
  2951.  
  2952.     /**
  2953.      * fetch a boolean value from a result set
  2954.      *
  2955.      * @param resource $result result identifier
  2956.      * @param int $row number of the row where the data can be found
  2957.      * @param int $field field number where the data can be found
  2958.      * @return mixed content of the specified data cell, a MDB error on failure
  2959.      * @access public
  2960.      */
  2961.     function fetchBoolean($result, $row, $field)
  2962.     {
  2963.         $value = $this->fetch($result, $row, $field);
  2964.         return($this->convertResult($value, MDB_TYPE_BOOLEAN));
  2965.     }
  2966.  
  2967.     // }}}
  2968.     // {{{ fetchFloat()
  2969.  
  2970.     /**
  2971.      * fetch a float value from a result set
  2972.      *
  2973.      * @param resource $result result identifier
  2974.      * @param int $row number of the row where the data can be found
  2975.      * @param int $field field number where the data can be found
  2976.      * @return mixed content of the specified data cell, a MDB error on failure
  2977.      * @access public
  2978.      */
  2979.     function fetchFloat($result, $row, $field)
  2980.     {
  2981.         $value = $this->fetch($result, $row, $field);
  2982.         return($this->convertResult($value, MDB_TYPE_FLOAT));
  2983.     }
  2984.  
  2985.     // }}}
  2986.     // {{{ fetchDecimal()
  2987.  
  2988.     /**
  2989.      * fetch a decimal value from a result set
  2990.      *
  2991.      * @param resource $result result identifier
  2992.      * @param int $row number of the row where the data can be found
  2993.      * @param int $field field number where the data can be found
  2994.      * @return mixed content of the specified data cell, a MDB error on failure
  2995.      * @access public
  2996.      */
  2997.     function fetchDecimal($result, $row, $field)
  2998.     {
  2999.         $value = $this->fetch($result, $row, $field);
  3000.         return($this->convertResult($value, MDB_TYPE_DECIMAL));
  3001.     }
  3002.  
  3003.     // }}}
  3004.     // {{{ numRows()
  3005.  
  3006.     /**
  3007.      * returns the number of rows in a result object
  3008.      *
  3009.      * @param ressource $result a valid result ressouce pointer
  3010.      * @return mixed MDB_Error or the number of rows
  3011.      * @access public
  3012.      */
  3013.     function numRows($result)
  3014.     {
  3015.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Num Rows: number of rows method not implemented'));
  3016.     }
  3017.  
  3018.     // }}}
  3019.     // {{{ freeResult()
  3020.  
  3021.     /**
  3022.      * Free the internal resources associated with $result.
  3023.      *
  3024.      * @param  $result result identifier
  3025.      * @return boolean TRUE on success, FALSE if $result is invalid
  3026.      * @access public
  3027.      */
  3028.     function freeResult($result)
  3029.     {
  3030.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Free Result: free result method not implemented'));
  3031.     }
  3032.  
  3033.     // }}}
  3034.     // {{{ getIntegerDeclaration()
  3035.  
  3036.     /**
  3037.      * Obtain DBMS specific SQL code portion needed to declare an integer type
  3038.      * field to be used in statements like CREATE TABLE.
  3039.      *
  3040.      * @param string $name name the field to be declared.
  3041.      * @param string $field associative array with the name of the properties
  3042.      *       of the field being declared as array indexes. Currently, the types
  3043.      *       of supported field properties are as follows:
  3044.      *
  3045.      *       unsigned
  3046.      *           Boolean flag that indicates whether the field should be
  3047.      *           declared as unsigned integer if possible.
  3048.      *
  3049.      *       default
  3050.      *           Integer value to be used as default for this field.
  3051.      *
  3052.      *       notnull
  3053.      *           Boolean flag that indicates whether this field is constrained
  3054.      *           to not be set to NULL.
  3055.      * @return string DBMS specific SQL code portion that should be used to
  3056.      *       declare the specified field.
  3057.      * @access public
  3058.      */
  3059.     function getIntegerDeclaration($name, $field)
  3060.     {
  3061.         if (isset($field['unsigned'])) {
  3062.             $this->warnings[] = "unsigned integer field \"$name\" is being
  3063.                 declared as signed integer";
  3064.         }
  3065.         return("$name INT" . (isset($field['default']) ? ' DEFAULT ' . $field['default'] : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3066.     }
  3067.  
  3068.     // }}}
  3069.     // {{{ getTextDeclaration()
  3070.  
  3071.     /**
  3072.      * Obtain DBMS specific SQL code portion needed to declare an text type
  3073.      * field to be used in statements like CREATE TABLE.
  3074.      *
  3075.      * @param string $name name the field to be declared.
  3076.      * @param string $field associative array with the name of the properties
  3077.      *       of the field being declared as array indexes. Currently, the types
  3078.      *       of supported field properties are as follows:
  3079.      *
  3080.      *       length
  3081.      *           Integer value that determines the maximum length of the text
  3082.      *           field. If this argument is missing the field should be
  3083.      *           declared to have the longest length allowed by the DBMS.
  3084.      *
  3085.      *       default
  3086.      *           Text value to be used as default for this field.
  3087.      *
  3088.      *       notnull
  3089.      *           Boolean flag that indicates whether this field is constrained
  3090.      *           to not be set to NULL.
  3091.      * @return string DBMS specific SQL code portion that should be used to
  3092.      *       declare the specified field.
  3093.      * @access public
  3094.      */
  3095.     function getTextDeclaration($name, $field)
  3096.     {
  3097.         return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3098.     }
  3099.  
  3100.     // }}}
  3101.     // {{{ getClobDeclaration()
  3102.  
  3103.     /**
  3104.      * Obtain DBMS specific SQL code portion needed to declare an character
  3105.      * large object type field to be used in statements like CREATE TABLE.
  3106.      *
  3107.      * @param string $name name the field to be declared.
  3108.      * @param string $field associative array with the name of the properties
  3109.      *       of the field being declared as array indexes. Currently, the types
  3110.      *       of supported field properties are as follows:
  3111.      *
  3112.      *       length
  3113.      *           Integer value that determines the maximum length of the large
  3114.      *           object field. If this argument is missing the field should be
  3115.      *           declared to have the longest length allowed by the DBMS.
  3116.      *
  3117.      *       notnull
  3118.      *           Boolean flag that indicates whether this field is constrained
  3119.      *           to not be set to NULL.
  3120.      * @return string DBMS specific SQL code portion that should be used to
  3121.      *       declare the specified field.
  3122.      * @access public
  3123.      */
  3124.     function getClobDeclaration($name, $field)
  3125.     {
  3126.         return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3127.     }
  3128.  
  3129.     // }}}
  3130.     // {{{ getBlobDeclaration()
  3131.  
  3132.     /**
  3133.      * Obtain DBMS specific SQL code portion needed to declare an binary large
  3134.      * object type field to be used in statements like CREATE TABLE.
  3135.      *
  3136.      * @param string $name name the field to be declared.
  3137.      * @param string $field associative array with the name of the properties
  3138.      *       of the field being declared as array indexes. Currently, the types
  3139.      *       of supported field properties are as follows:
  3140.      *
  3141.      *       length
  3142.      *           Integer value that determines the maximum length of the large
  3143.      *           object field. If this argument is missing the field should be
  3144.      *           declared to have the longest length allowed by the DBMS.
  3145.      *
  3146.      *       notnull
  3147.      *           Boolean flag that indicates whether this field is constrained
  3148.      *           to not be set to NULL.
  3149.      * @return string DBMS specific SQL code portion that should be used to
  3150.      *       declare the specified field.
  3151.      * @access public
  3152.      */
  3153.     function getBlobDeclaration($name, $field)
  3154.     {
  3155.         return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3156.     }
  3157.  
  3158.     // }}}
  3159.     // {{{ getBooleanDeclaration()
  3160.  
  3161.     /**
  3162.      * Obtain DBMS specific SQL code portion needed to declare a boolean type
  3163.      * field to be used in statements like CREATE TABLE.
  3164.      *
  3165.      * @param string $name name the field to be declared.
  3166.      * @param string $field associative array with the name of the properties
  3167.      *       of the field being declared as array indexes. Currently, the types
  3168.      *       of supported field properties are as follows:
  3169.      *
  3170.      *       default
  3171.      *           Boolean value to be used as default for this field.
  3172.      *
  3173.      *       notnullL
  3174.      *           Boolean flag that indicates whether this field is constrained
  3175.      *           to not be set to NULL.
  3176.      * @return string DBMS specific SQL code portion that should be used to
  3177.      *       declare the specified field.
  3178.      * @access public
  3179.      */
  3180.     function getBooleanDeclaration($name, $field)
  3181.     {
  3182.         return("$name CHAR (1)" . (isset($field['default']) ? ' DEFAULT ' . $this->getBooleanValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3183.     }
  3184.  
  3185.     // }}}
  3186.     // {{{ getDateDeclaration()
  3187.  
  3188.     /**
  3189.      * Obtain DBMS specific SQL code portion needed to declare a date type
  3190.      * field to be used in statements like CREATE TABLE.
  3191.      *
  3192.      * @param string $name name the field to be declared.
  3193.      * @param string $field associative array with the name of the properties
  3194.      *       of the field being declared as array indexes. Currently, the types
  3195.      *       of supported field properties are as follows:
  3196.      *
  3197.      *       default
  3198.      *           Date value to be used as default for this field.
  3199.      *
  3200.      *       notnull
  3201.      *           Boolean flag that indicates whether this field is constrained
  3202.      *           to not be set to NULL.
  3203.      * @return string DBMS specific SQL code portion that should be used to
  3204.      *       declare the specified field.
  3205.      * @access public
  3206.      */
  3207.     function getDateDeclaration($name, $field)
  3208.     {
  3209.         return("$name CHAR (" . strlen("YYYY-MM-DD") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getDateValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3210.     }
  3211.  
  3212.     // }}}
  3213.     // {{{ getTimestampDeclaration()
  3214.  
  3215.     /**
  3216.      * Obtain DBMS specific SQL code portion needed to declare a timestamp
  3217.      * field to be used in statements like CREATE TABLE.
  3218.      *
  3219.      * @param string $name name the field to be declared.
  3220.      * @param string $field associative array with the name of the properties
  3221.      *       of the field being declared as array indexes. Currently, the types
  3222.      *       of supported field properties are as follows:
  3223.      *
  3224.      *       default
  3225.      *           Timestamp value to be used as default for this field.
  3226.      *
  3227.      *       notnull
  3228.      *           Boolean flag that indicates whether this field is constrained
  3229.      *           to not be set to NULL.
  3230.      * @return string DBMS specific SQL code portion that should be used to
  3231.      *       declare the specified field.
  3232.      * @access public
  3233.      */
  3234.     function getTimestampDeclaration($name, $field)
  3235.     {
  3236.         return("$name CHAR (" . strlen("YYYY-MM-DD HH:MM:SS") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getTimestampValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3237.     }
  3238.  
  3239.     // }}}
  3240.     // {{{ getTimeDeclaration()
  3241.  
  3242.     /**
  3243.      * Obtain DBMS specific SQL code portion needed to declare a time
  3244.      * field to be used in statements like CREATE TABLE.
  3245.      *
  3246.      * @param string $name name the field to be declared.
  3247.      * @param string $field associative array with the name of the properties
  3248.      *       of the field being declared as array indexes. Currently, the types
  3249.      *       of supported field properties are as follows:
  3250.      *
  3251.      *       default
  3252.      *           Time value to be used as default for this field.
  3253.      *
  3254.      *       notnull
  3255.      *           Boolean flag that indicates whether this field is constrained
  3256.      *           to not be set to NULL.
  3257.      * @return string DBMS specific SQL code portion that should be used to
  3258.      *       declare the specified field.
  3259.      * @access public
  3260.      */
  3261.     function getTimeDeclaration($name, $field)
  3262.     {
  3263.         return("$name CHAR (" . strlen("HH:MM:SS") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getTimeValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3264.     }
  3265.  
  3266.     // }}}
  3267.     // {{{ getFloatDeclaration()
  3268.  
  3269.     /**
  3270.      * Obtain DBMS specific SQL code portion needed to declare a float type
  3271.      * field to be used in statements like CREATE TABLE.
  3272.      *
  3273.      * @param string $name name the field to be declared.
  3274.      * @param string $field associative array with the name of the properties
  3275.      *       of the field being declared as array indexes. Currently, the types
  3276.      *       of supported field properties are as follows:
  3277.      *
  3278.      *       default
  3279.      *           Float value to be used as default for this field.
  3280.      *
  3281.      *       notnull
  3282.      *           Boolean flag that indicates whether this field is constrained
  3283.      *           to not be set to NULL.
  3284.      * @return string DBMS specific SQL code portion that should be used to
  3285.      *       declare the specified field.
  3286.      * @access public
  3287.      */
  3288.     function getFloatDeclaration($name, $field)
  3289.     {
  3290.         return("$name TEXT " . (isset($field['default']) ? ' DEFAULT ' . $this->getFloatValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3291.     }
  3292.  
  3293.     // }}}
  3294.     // {{{ getDecimalDeclaration()
  3295.  
  3296.     /**
  3297.      * Obtain DBMS specific SQL code portion needed to declare a decimal type
  3298.      * field to be used in statements like CREATE TABLE.
  3299.      *
  3300.      * @param string $name name the field to be declared.
  3301.      * @param string $field associative array with the name of the properties
  3302.      *       of the field being declared as array indexes. Currently, the types
  3303.      *       of supported field properties are as follows:
  3304.      *
  3305.      *       default
  3306.      *           Decimal value to be used as default for this field.
  3307.      *
  3308.      *       notnull
  3309.      *           Boolean flag that indicates whether this field is constrained
  3310.      *           to not be set to NULL.
  3311.      * @return string DBMS specific SQL code portion that should be used to
  3312.      *       declare the specified field.
  3313.      * @access public
  3314.      */
  3315.     function getDecimalDeclaration($name, $field)
  3316.     {
  3317.         return("$name TEXT " . (isset($field['default']) ? ' DEFAULT ' . $this->getDecimalValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  3318.     }
  3319.  
  3320.     // }}}
  3321.     // {{{ getIntegerValue()
  3322.  
  3323.     /**
  3324.      * Convert a text value into a DBMS specific format that is suitable to
  3325.      * compose query statements.
  3326.      *
  3327.      * @param string $value text string value that is intended to be converted.
  3328.      * @return string text string that represents the given argument value in
  3329.      *       a DBMS specific format.
  3330.      * @access public
  3331.      */
  3332.     function getIntegerValue($value)
  3333.     {
  3334.         return(($value === NULL) ? 'NULL' : (int)$value);
  3335.     }
  3336.  
  3337.     // }}}
  3338.     // {{{ getTextValue()
  3339.  
  3340.     /**
  3341.      * Convert a text value into a DBMS specific format that is suitable to
  3342.      * compose query statements.
  3343.      *
  3344.      * @param string $value text string value that is intended to be converted.
  3345.      * @return string text string that already contains any DBMS specific
  3346.      *       escaped character sequences.
  3347.      * @access public
  3348.      */
  3349.     function getTextValue($value)
  3350.     {
  3351.         return(($value === NULL) ? 'NULL' : "'".$this->_quote($value)."'");
  3352.     }
  3353.  
  3354.     // }}}
  3355.     // {{{ getClobValue()
  3356.  
  3357.     /**
  3358.      * Convert a text value into a DBMS specific format that is suitable to
  3359.      * compose query statements.
  3360.      *
  3361.      * @param resource $prepared_query query handle from prepare()
  3362.      * @param  $parameter
  3363.      * @param  $clob
  3364.      * @return string text string that represents the given argument value in
  3365.      *       a DBMS specific format.
  3366.      * @access public
  3367.      */
  3368.     function getClobValue($prepared_query, $parameter, $clob)
  3369.     {
  3370.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  3371.             'Get CLOB field value: prepared queries with values of type "clob" are not yet supported'));
  3372.     }
  3373.  
  3374.     // }}}
  3375.     // {{{ freeClobValue()
  3376.  
  3377.     /**
  3378.      * free a character large object
  3379.      *
  3380.      * @param resource $prepared_query query handle from prepare()
  3381.      * @param string $blob
  3382.      * @param string $value
  3383.      * @access public
  3384.      */
  3385.     function freeClobValue($prepared_query, $clob, &$value)
  3386.     {
  3387.     }
  3388.  
  3389.     // }}}
  3390.     // {{{ getBlobValue()
  3391.  
  3392.     /**
  3393.      * Convert a text value into a DBMS specific format that is suitable to
  3394.      * compose query statements.
  3395.      *
  3396.      * @param resource $prepared_query query handle from prepare()
  3397.      * @param  $parameter
  3398.      * @param  $blob
  3399.      * @return string text string that represents the given argument value in
  3400.      *       a DBMS specific format.
  3401.      * @access public
  3402.      */
  3403.     function getBlobValue($prepared_query, $parameter, $blob)
  3404.     {
  3405.         return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  3406.             'Get BLOB field value: prepared queries with values of type "blob" are not yet supported'));
  3407.     }
  3408.  
  3409.     // }}}
  3410.     // {{{ freeBlobValue()
  3411.  
  3412.     /**
  3413.      * free a binary large object
  3414.      *
  3415.      * @param resource $prepared_query query handle from prepare()
  3416.      * @param string $blob
  3417.      * @param string $value
  3418.      * @access public
  3419.      */
  3420.     function freeBlobValue($prepared_query, $blob, &$value)
  3421.     {
  3422.     }
  3423.  
  3424.     // }}}
  3425.     // {{{ getBooleanValue()
  3426.  
  3427.     /**
  3428.      * Convert a text value into a DBMS specific format that is suitable to
  3429.      * compose query statements.
  3430.      *
  3431.      * @param string $value text string value that is intended to be converted.
  3432.      * @return string text string that represents the given argument value in
  3433.      *       a DBMS specific format.
  3434.      * @access public
  3435.      */
  3436.     function getBooleanValue($value)
  3437.     {
  3438.         return(($value === NULL) ? 'NULL' : ($value ? "'Y'" : "'N'"));
  3439.     }
  3440.  
  3441.     // }}}
  3442.     // {{{ getDateValue()
  3443.  
  3444.     /**
  3445.      * Convert a text value into a DBMS specific format that is suitable to
  3446.      * compose query statements.
  3447.      *
  3448.      * @param string $value text string value that is intended to be converted.
  3449.      * @return string text string that represents the given argument value in
  3450.      *       a DBMS specific format.
  3451.      * @access public
  3452.      */
  3453.     function getDateValue($value)
  3454.     {
  3455.         return(($value === NULL) ? 'NULL' : "'$value'");
  3456.     }
  3457.  
  3458.     // }}}
  3459.     // {{{ getTimestampValue()
  3460.  
  3461.     /**
  3462.      * Convert a text value into a DBMS specific format that is suitable to
  3463.      * compose query statements.
  3464.      *
  3465.      * @param string $value text string value that is intended to be converted.
  3466.      * @return string text string that represents the given argument value in
  3467.      *       a DBMS specific format.
  3468.      * @access public
  3469.      */
  3470.     function getTimestampValue($value)
  3471.     {
  3472.         return(($value === NULL) ? 'NULL' : "'$value'");
  3473.     }
  3474.  
  3475.     // }}}
  3476.     // {{{ getTimeValue()
  3477.  
  3478.     /**
  3479.      * Convert a text value into a DBMS specific format that is suitable to
  3480.      *       compose query statements.
  3481.      *
  3482.      * @param string $value text string value that is intended to be converted.
  3483.      * @return string text string that represents the given argument value in
  3484.      *       a DBMS specific format.
  3485.      * @access public
  3486.      */
  3487.     function getTimeValue($value)
  3488.     {
  3489.         return(($value === NULL) ? 'NULL' : "'$value'");
  3490.     }
  3491.  
  3492.     // }}}
  3493.     // {{{ getFloatValue()
  3494.  
  3495.     /**
  3496.      * Convert a text value into a DBMS specific format that is suitable to
  3497.      * compose query statements.
  3498.      *
  3499.      * @param string $value text string value that is intended to be converted.
  3500.      * @return string text string that represents the given argument value in
  3501.      *       a DBMS specific format.
  3502.      * @access public
  3503.      */
  3504.     function getFloatValue($value)
  3505.     {
  3506.         return(($value === NULL) ? 'NULL' : "'$value'");
  3507.     }
  3508.  
  3509.     // }}}
  3510.     // {{{ getDecimalValue()
  3511.  
  3512.     /**
  3513.      * Convert a text value into a DBMS specific format that is suitable to
  3514.      * compose query statements.
  3515.      *
  3516.      * @param string $value text string value that is intended to be converted.
  3517.      * @return string text string that represents the given argument value in
  3518.      *       a DBMS specific format.
  3519.      * @access public
  3520.      */
  3521.     function getDecimalValue($value)
  3522.     {
  3523.         return(($value === NULL) ? 'NULL' : "'$value'");
  3524.     }
  3525.  
  3526.     // }}}
  3527.     // {{{ getValue()
  3528.  
  3529.     /**
  3530.      * Convert a text value into a DBMS specific format that is suitable to
  3531.      * compose query statements.
  3532.      *
  3533.      * @param string $type type to which the value should be converted to
  3534.      * @param string $value text string value that is intended to be converted.
  3535.      * @return string text string that represents the given argument value in
  3536.      *       a DBMS specific format.
  3537.      * @access public
  3538.      */
  3539.     function getValue($type, $value)
  3540.     {
  3541.         if (empty($type)) {
  3542.             return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
  3543.                 'getValue: called without type to convert to'));
  3544.         }
  3545.         if (method_exists($this,"get{$type}Value")) {
  3546.             return $this->{"get{$type}Value"}($value);
  3547.         }
  3548.         return $value;
  3549.     }
  3550.  
  3551.     // }}}
  3552.     // {{{ support()
  3553.  
  3554.     /**
  3555.      * Tell whether a DB implementation or its backend extension
  3556.      * supports a given feature.
  3557.      *
  3558.      * @param string $feature name of the feature (see the MDB class doc)
  3559.      * @return boolean whether this DB implementation supports $feature
  3560.      * @access public
  3561.      */
  3562.     function support($feature)
  3563.     {
  3564.         return(isset($this->supported[$feature]) && $this->supported[$feature]);
  3565.     }
  3566.  
  3567.     // }}}
  3568.     // {{{ getSequenceName()
  3569.  
  3570.     /**
  3571.      * adds sequence name formating to a sequence name
  3572.      *
  3573.      * @param string $sqn name of the sequence
  3574.      * @return string formatted sequence name
  3575.      * @access public
  3576.      */
  3577.     function getSequenceName($sqn)
  3578.     {
  3579.         return sprintf($this->options['seqname_format'],
  3580.             preg_replace('/[^a-z0-9_]/i', '_', $sqn));
  3581.     }
  3582.  
  3583.     // }}}
  3584.     // {{{ nextId()
  3585.  
  3586.     /**
  3587.      * returns the next free id of a sequence
  3588.      *
  3589.      * @param string $seq_name name of the sequence
  3590.      * @param boolean $ondemand when TRUE the seqence is
  3591.      *                           automatic created, if it
  3592.      *                           not exists
  3593.      * @return mixed MDB_Error or id
  3594.      * @access public
  3595.      */
  3596.     function nextId($seq_name, $ondemand = FALSE)
  3597.     {
  3598.         return($this->raiseError(MDB_ERROR_NOT_CAPABLE, NULL, NULL,
  3599.             'Next Sequence: getting next sequence value not supported'));
  3600.     }
  3601.  
  3602.     // }}}
  3603.     // {{{ currId()
  3604.  
  3605.     /**
  3606.      * returns the current id of a sequence
  3607.      *
  3608.      * @param string $seq_name name of the sequence
  3609.      * @return mixed MDB_Error or id
  3610.      * @access public
  3611.      */
  3612.     function currId($seq_name)
  3613.     {
  3614.         $this->warnings[] = 'database does not support getting current
  3615.             sequence value, the sequence value was incremented';
  3616.         $this->expectError(MDB_ERROR_NOT_CAPABLE);
  3617.         $id = $this->nextId($seq_name);
  3618.         $this->popExpect(MDB_ERROR_NOT_CAPABLE);
  3619.         if (MDB::isError($id)) {
  3620.             if ($id->getCode() == MDB_ERROR_NOT_CAPABLE) {
  3621.                 return($this->raiseError(MDB_ERROR_NOT_CAPABLE, NULL, NULL,
  3622.                     'Current Sequence: getting current sequence value not supported'));
  3623.             }
  3624.             return($id);
  3625.         }
  3626.         return($id);
  3627.     }
  3628.  
  3629.     // }}}
  3630.     // {{{ fetchInto()
  3631.  
  3632.     /**
  3633.      * Fetch a row and return data in an array.
  3634.      *
  3635.      * @param resource $result result identifier
  3636.      * @param int $fetchmode ignored
  3637.      * @param int $rownum the row number to fetch
  3638.      * @return mixed data array or NULL on success, a MDB error on failure
  3639.      * @access public
  3640.      */
  3641.     function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL)
  3642.     {
  3643.         $result_value = intval($result);
  3644.         if (MDB::isError($this->endOfResult($result))) {
  3645.             $this->freeResult($result);
  3646.             $result = $this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL,
  3647.                 'Fetch field: result set is empty');
  3648.         }
  3649.         if ($rownum == NULL) {
  3650.             ++$this->highest_fetched_row[$result_value];
  3651.             $rownum = $this->highest_fetched_row[$result_value];
  3652.         } else {
  3653.             $this->highest_fetched_row[$result_value] =
  3654.                 max($this->highest_fetched_row[$result_value], $row);
  3655.         }
  3656.         if ($fetchmode == MDB_FETCHMODE_DEFAULT) {
  3657.             $fetchmode = $this->fetchmode;
  3658.         }
  3659.         $columns = $this->numCols($result);
  3660.         if (MDB::isError($columns)) {
  3661.             return($columns);
  3662.         }
  3663.         if ($fetchmode & MDB_FETCHMODE_ASSOC) {
  3664.             $column_names = $this->getColumnNames($result);
  3665.         }
  3666.         for($column = 0; $column < $columns; $column++) {
  3667.             if (!$this->resultIsNull($result, $rownum, $column)) {
  3668.                 $value = $this->fetch($result, $rownum, $column);
  3669.                 if ($value === FALSE) {
  3670.                     if ($this->options['autofree']) {
  3671.                         $this->freeResult($result);
  3672.                     }
  3673.                     return(NULL);
  3674.                 } elseif (MDB::isError($value)) {
  3675.                     if ($value->getMessage() == '') {
  3676.                         if ($this->options['autofree']) {
  3677.                             $this->freeResult($result);
  3678.                         }
  3679.                         return(NULL);
  3680.                     } else {
  3681.                         return($value);
  3682.                     }
  3683.                 }
  3684.             }
  3685.             $row[$column] = $value;
  3686.         }
  3687.         if ($fetchmode & MDB_FETCHMODE_ASSOC) {
  3688.             $row = array_combine($column_names, $row);
  3689.             if (is_array($row) && $this->options['optimize'] == 'portability') {
  3690.                 $row = array_change_key_case($row, CASE_LOWER);
  3691.             }
  3692.         }
  3693.         if (isset($this->result_types[$result_value])) {
  3694.             $row = $this->convertResultRow($result, $row);
  3695.         }
  3696.         return($row);
  3697.     }
  3698.  
  3699.     // }}}
  3700.     // {{{ fetchOne()
  3701.  
  3702.     /**
  3703.      * Fetch and return a field of data (it uses fetchInto for that)
  3704.      *
  3705.      * @param resource $result result identifier
  3706.      * @return mixed data on success, a MDB error on failure
  3707.      * @access public
  3708.      */
  3709.     function fetchOne($result)
  3710.     {
  3711.         $row = $this->fetchInto($result, MDB_FETCHMODE_ORDERED);
  3712.         if (!$this->options['autofree'] || $row != NULL) {
  3713.             $this->freeResult($result);
  3714.         }
  3715.         if (is_array($row)) {
  3716.             return($row[0]);
  3717.         }
  3718.         return($row);
  3719.     }
  3720.  
  3721.     // }}}
  3722.     // {{{ fetchRow()
  3723.  
  3724.     /**
  3725.      * Fetch and return a row of data (it uses fetchInto for that)
  3726.      *
  3727.      * @param resource $result result identifier
  3728.      * @param int $fetchmode how the array data should be indexed
  3729.      * @param int $rownum the row number to fetch
  3730.      * @return mixed data array on success, a MDB error on failure
  3731.      * @access public
  3732.      */
  3733.     function fetchRow($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL)
  3734.     {
  3735.         $row = $this->fetchInto($result, $fetchmode, $rownum);
  3736.         if (!$this->options['autofree'] || $row != NULL) {
  3737.             $this->freeResult($result);
  3738.         }
  3739.         return($row);
  3740.     }
  3741.  
  3742.     // }}}
  3743.     // {{{ fetchCol()
  3744.  
  3745.     /**
  3746.      * Fetch and return a column of data (it uses fetchInto for that)
  3747.      *
  3748.      * @param resource $result result identifier
  3749.      * @param int $colnum the row number to fetch
  3750.      * @return mixed data array on success, a MDB error on failure
  3751.      * @access public
  3752.      */
  3753.     function fetchCol($result, $colnum = 0)
  3754.     {
  3755.         $fetchmode = is_numeric($colnum) ? MDB_FETCHMODE_ORDERED : MDB_FETCHMODE_ASSOC;
  3756.         $column = array();
  3757.         $row = $this->fetchInto($result, $fetchmode);
  3758.         if (is_array($row)) {
  3759.             if (!array_key_exists($colnum, $row)) {
  3760.                 return($this->raiseError(MDB_ERROR_TRUNCATED));
  3761.             }
  3762.             do {
  3763.                 $column[] = $row[$colnum];
  3764.             } while (is_array($row = $this->fetchInto($result, $fetchmode)));
  3765.         }
  3766.         if (!$this->options['autofree']) {
  3767.             $this->freeResult($result);
  3768.         }
  3769.         if (MDB::isError($row)) {
  3770.             return($row);
  3771.         }
  3772.         return($column);
  3773.     }
  3774.  
  3775.     // }}}
  3776.     // {{{ fetchAll()
  3777.  
  3778.     /**
  3779.      * Fetch and return a column of data (it uses fetchInto for that)
  3780.      *
  3781.      * @param resource $result result identifier
  3782.      * @param int $fetchmode how the array data should be indexed
  3783.      * @param boolean $rekey if set to TRUE, the $all will have the first
  3784.      *       column as its first dimension
  3785.      * @param boolean $force_array used only when the query returns exactly
  3786.      *       two columns. If TRUE, the values of the returned array will be
  3787.      *       one-element arrays instead of scalars.
  3788.      * @param boolean $group if TRUE, the values of the returned array is
  3789.      *       wrapped in another array.  If the same key value (in the first
  3790.      *       column) repeats itself, the values will be appended to this array
  3791.      *       instead of overwriting the existing values.
  3792.      * @return mixed data array on success, a MDB error on failure
  3793.      * @access public
  3794.      * @see getAssoc()
  3795.      */
  3796.     function fetchAll($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rekey = FALSE, $force_array = FALSE, $group = FALSE)
  3797.     {
  3798.         if ($rekey) {
  3799.             $cols = $this->numCols($result);
  3800.             if (MDB::isError($cols)) {
  3801.                 return($cols);
  3802.             }
  3803.             if ($cols < 2) {
  3804.                 return($this->raiseError(MDB_ERROR_TRUNCATED));
  3805.             }
  3806.         }
  3807.         $all = array();
  3808.         while (is_array($row = $this->fetchInto($result, $fetchmode))) {
  3809.             if ($rekey) {
  3810.                 if ($fetchmode & MDB_FETCHMODE_ASSOC) {
  3811.                     $key = reset($row);
  3812.                     unset($row[key($row)]);
  3813.                 } else {
  3814.                     $key = array_shift($row);
  3815.                 }
  3816.                 if (!$force_array && count($row) == 1) {
  3817.                     $row = array_shift($row);
  3818.                 }
  3819.                 if ($group) {
  3820.                     $all[$key][] = $row;
  3821.                 } else {
  3822.                     $all[$key] = $row;
  3823.                 }
  3824.             } else {
  3825.                 if ($fetchmode & MDB_FETCHMODE_FLIPPED) {
  3826.                     foreach ($row as $key => $val) {
  3827.                         $all[$key][] = $val;
  3828.                     }
  3829.                 } else {
  3830.                    $all[] = $row;
  3831.                 }
  3832.             }
  3833.         }
  3834.         if (!$this->options['autofree']) {
  3835.             $this->freeResult($result);
  3836.         }
  3837.         if (MDB::isError($row)) {
  3838.             return($row);
  3839.         }
  3840.         return($all);
  3841.     }
  3842.  
  3843.     // }}}
  3844.     // {{{ queryOne()
  3845.  
  3846.     /**
  3847.      * Execute the specified query, fetch the value from the first column of
  3848.      * the first row of the result set and then frees
  3849.      * the result set.
  3850.      *
  3851.      * @param string $query the SELECT query statement to be executed.
  3852.      * @param string $type optional argument that specifies the expected
  3853.      *       datatype of the result set field, so that an eventual conversion
  3854.      *       may be performed. The default datatype is text, meaning that no
  3855.      *       conversion is performed
  3856.      * @return mixed field value on success, a MDB error on failure
  3857.      * @access public
  3858.      */
  3859.     function queryOne($query, $type = NULL)
  3860.     {
  3861.         if ($type != NULL) {
  3862.             $type = array($type);
  3863.         }
  3864.         $result = $this->query($query, $type);
  3865.         if (MDB::isError($result)) {
  3866.             return($result);
  3867.         }
  3868.         return($this->fetchOne($result));
  3869.     }
  3870.  
  3871.     // }}}
  3872.     // {{{ queryRow()
  3873.  
  3874.     /**
  3875.      * Execute the specified query, fetch the values from the first
  3876.      * row of the result set into an array and then frees
  3877.      * the result set.
  3878.      *
  3879.      * @param string $query the SELECT query statement to be executed.
  3880.      * @param array $types optional array argument that specifies a list of
  3881.      *       expected datatypes of the result set columns, so that the eventual
  3882.      *       conversions may be performed. The default list of datatypes is
  3883.      *       empty, meaning that no conversion is performed.
  3884.      * @param int $fetchmode how the array data should be indexed
  3885.      * @return mixed data array on success, a MDB error on failure
  3886.      * @access public
  3887.      */
  3888.     function queryRow($query, $types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT)
  3889.     {
  3890.         $result = $this->query($query, $types);
  3891.         if (MDB::isError($result)) {
  3892.             return($result);
  3893.         }
  3894.         return($this->fetchRow($result, $fetchmode));
  3895.     }
  3896.  
  3897.     // }}}
  3898.     // {{{ queryCol()
  3899.  
  3900.     /**
  3901.      * Execute the specified query, fetch the value from the first column of
  3902.      * each row of the result set into an array and then frees the result set.
  3903.      *
  3904.      * @param string $query the SELECT query statement to be executed.
  3905.      * @param string $type optional argument that specifies the expected
  3906.      *       datatype of the result set field, so that an eventual conversion
  3907.      *       may be performed. The default datatype is text, meaning that no
  3908.      *       conversion is performed
  3909.      * @param int $colnum the row number to fetch
  3910.      * @return mixed data array on success, a MDB error on failure
  3911.      * @access public
  3912.      */
  3913.     function queryCol($query, $type = NULL, $colnum = 0)
  3914.     {
  3915.         if ($type != NULL) {
  3916.             $type = array($type);
  3917.         }
  3918.         $result = $this->query($query, $type);
  3919.         if (MDB::isError($result)) {
  3920.             return($result);
  3921.         }
  3922.         return($this->fetchCol($result, $colnum));
  3923.     }
  3924.  
  3925.     // }}}
  3926.     // {{{ queryAll()
  3927.  
  3928.     /**
  3929.      * Execute the specified query, fetch all the rows of the result set into
  3930.      * a two dimensional array and then frees the result set.
  3931.      *
  3932.      * @param string $query the SELECT query statement to be executed.
  3933.      * @param array $types optional array argument that specifies a list of
  3934.      *       expected datatypes of the result set columns, so that the eventual
  3935.      *       conversions may be performed. The default list of datatypes is
  3936.      *       empty, meaning that no conversion is performed.
  3937.      * @param int $fetchmode how the array data should be indexed
  3938.      * @param boolean $rekey if set to TRUE, the $all will have the first
  3939.      *       column as its first dimension
  3940.      * @param boolean $force_array used only when the query returns exactly
  3941.      *       two columns. If TRUE, the values of the returned array will be
  3942.      *       one-element arrays instead of scalars.
  3943.      * @param boolean $group if TRUE, the values of the returned array is
  3944.      *       wrapped in another array.  If the same key value (in the first
  3945.      *       column) repeats itself, the values will be appended to this array
  3946.      *       instead of overwriting the existing values.
  3947.      * @return mixed data array on success, a MDB error on failure
  3948.      * @access public
  3949.      */
  3950.     function queryAll($query, $types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT,
  3951.         $rekey = FALSE, $force_array = FALSE, $group = FALSE)
  3952.     {
  3953.         if (MDB::isError($result = $this->query($query, $types))) {
  3954.             return($result);
  3955.         }
  3956.         return($this->fetchAll($result, $fetchmode, $rekey, $force_array, $group));
  3957.     }
  3958.  
  3959.     // }}}
  3960.     // {{{ getOne()
  3961.  
  3962.     /**
  3963.      * Fetch the first column of the first row of data returned from
  3964.      * a query.  Takes care of doing the query and freeing the results
  3965.      * when finished.
  3966.      *
  3967.      * @param string $query the SQL query
  3968.      * @param string $type string that contains the type of the column in the
  3969.      *       result set
  3970.      * @param array $params if supplied, prepare/execute will be used
  3971.      *       with this array as execute parameters
  3972.      * @param array $param_types array that contains the types of the values
  3973.      *       defined in $params
  3974.      * @return mixed MDB_Error or the returned value of the query
  3975.      * @access public
  3976.      */
  3977.     function getOne($query, $type = NULL, $params = array(), $param_types = NULL)
  3978.     {
  3979.         if ($type != NULL) {
  3980.             $type = array($type);
  3981.         }
  3982.         settype($params, 'array');
  3983.         if (count($params) > 0) {
  3984.             $prepared_query = $this->prepareQuery($query);
  3985.             if (MDB::isError($prepared_query)) {
  3986.                 return($prepared_query);
  3987.             }
  3988.             $this->setParamArray($prepared_query, $params, $param_types);
  3989.             $result = $this->executeQuery($prepared_query, $type);
  3990.         } else {
  3991.             $result = $this->query($query, $type);
  3992.         }
  3993.  
  3994.         if (MDB::isError($result)) {
  3995.             return($result);
  3996.         }
  3997.  
  3998.         $value = $this->fetchOne($result, MDB_FETCHMODE_ORDERED);
  3999.         if (MDB::isError($value)) {
  4000.             return($value);
  4001.         }
  4002.         if (isset($prepared_query)) {
  4003.             $result = $this->freePreparedQuery($prepared_query);
  4004.             if (MDB::isError($result)) {
  4005.                 return($result);
  4006.             }
  4007.         }
  4008.  
  4009.         return($value);
  4010.     }
  4011.  
  4012.     // }}}
  4013.     // {{{ getRow()
  4014.  
  4015.     /**
  4016.      * Fetch the first row of data returned from a query.  Takes care
  4017.      * of doing the query and freeing the results when finished.
  4018.      *
  4019.      * @param string $query the SQL query
  4020.      * @param array $types array that contains the types of the columns in
  4021.      *       the result set
  4022.      * @param array $params array if supplied, prepare/execute will be used
  4023.      *       with this array as execute parameters
  4024.      * @param array $param_types array that contains the types of the values
  4025.      *       defined in $params
  4026.      * @param integer $fetchmode the fetch mode to use
  4027.      * @return array the first row of results as an array indexed from
  4028.      * 0, or a MDB error code.
  4029.      * @access public
  4030.      */
  4031.     function getRow($query, $types = NULL, $params = array(), $param_types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT)
  4032.     {
  4033.         settype($params, 'array');
  4034.         if (count($params) > 0) {
  4035.             $prepared_query = $this->prepareQuery($query);
  4036.             if (MDB::isError($prepared_query)) {
  4037.                 return($prepared_query);
  4038.             }
  4039.             $this->setParamArray($prepared_query, $params, $param_types);
  4040.             $result = $this->executeQuery($prepared_query, $types);
  4041.         } else {
  4042.             $result = $this->query($query, $types);
  4043.         }
  4044.  
  4045.         if (MDB::isError($result)) {
  4046.             return($result);
  4047.         }
  4048.  
  4049.         $row = $this->fetchRow($result, $fetchmode);
  4050.         if (MDB::isError($row)) {
  4051.             return($row);
  4052.         }
  4053.         if (isset($prepared_query)) {
  4054.             $result = $this->freePreparedQuery($prepared_query);
  4055.             if (MDB::isError($result)) {
  4056.                 return($result);
  4057.             }
  4058.         }
  4059.  
  4060.         return($row);
  4061.     }
  4062.  
  4063.     // }}}
  4064.     // {{{ getCol()
  4065.  
  4066.     /**
  4067.      * Fetch a single column from a result set and return it as an
  4068.      * indexed array.
  4069.      *
  4070.      * @param string $query the SQL query
  4071.      * @param string $type string that contains the type of the column in the
  4072.      *       result set
  4073.      * @param array $params array if supplied, prepare/execute will be used
  4074.      *       with this array as execute parameters
  4075.      * @param array $param_types array that contains the types of the values
  4076.      *       defined in $params
  4077.      * @param mixed $colnum which column to return(integer [column number,
  4078.      *       starting at 0] or string [column name])
  4079.      * @return array an indexed array with the data from the first
  4080.      * row at index 0, or a MDB error code.
  4081.      * @access public
  4082.      */
  4083.     function getCol($query, $type = NULL, $params = array(), $param_types = NULL, $colnum = 0)
  4084.     {
  4085.         if ($type != NULL) {
  4086.             $type = array($type);
  4087.         }
  4088.         settype($params, 'array');
  4089.         if (count($params) > 0) {
  4090.             $prepared_query = $this->prepareQuery($query);
  4091.  
  4092.             if (MDB::isError($prepared_query)) {
  4093.                 return($prepared_query);
  4094.             }
  4095.             $this->setParamArray($prepared_query, $params, $param_types);
  4096.             $result = $this->executeQuery($prepared_query, $type);
  4097.         } else {
  4098.             $result = $this->query($query, $type);
  4099.         }
  4100.  
  4101.         if (MDB::isError($result)) {
  4102.             return($result);
  4103.         }
  4104.  
  4105.         $col = $this->fetchCol($result, $colnum);
  4106.         if (MDB::isError($col)) {
  4107.             return($col);
  4108.         }
  4109.         if (isset($prepared_query)) {
  4110.             $result = $this->freePreparedQuery($prepared_query);
  4111.             if (MDB::isError($result)) {
  4112.                 return($result);
  4113.             }
  4114.         }
  4115.         return($col);
  4116.     }
  4117.  
  4118.     // }}}
  4119.     // {{{ getAssoc()
  4120.  
  4121.     /**
  4122.      * Fetch the entire result set of a query and return it as an
  4123.      * associative array using the first column as the key.
  4124.      *
  4125.      * If the result set contains more than two columns, the value
  4126.      * will be an array of the values from column 2-n.  If the result
  4127.      * set contains only two columns, the returned value will be a
  4128.      * scalar with the value of the second column (unless forced to an
  4129.      * array with the $force_array parameter).  A MDB error code is
  4130.      * returned on errors.  If the result set contains fewer than two
  4131.      * columns, a MDB_ERROR_TRUNCATED error is returned.
  4132.      *
  4133.      * For example, if the table 'mytable' contains:
  4134.      *
  4135.      *   ID      TEXT       DATE
  4136.      * --------------------------------
  4137.      *   1       'one'      944679408
  4138.      *   2       'two'      944679408
  4139.      *   3       'three'    944679408
  4140.      *
  4141.      * Then the call getAssoc('SELECT id,text FROM mytable') returns:
  4142.      *    array(
  4143.      *      '1' => 'one',
  4144.      *      '2' => 'two',
  4145.      *      '3' => 'three',
  4146.      *    )
  4147.      *
  4148.      * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
  4149.      *    array(
  4150.      *      '1' => array('one', '944679408'),
  4151.      *      '2' => array('two', '944679408'),
  4152.      *      '3' => array('three', '944679408')
  4153.      *    )
  4154.      *
  4155.      * If the more than one row occurs with the same value in the
  4156.      * first column, the last row overwrites all previous ones by
  4157.      * default.  Use the $group parameter if you don't want to
  4158.      * overwrite like this.  Example:
  4159.      *
  4160.      * getAssoc('SELECT category,id,name FROM mytable', NULL, NULL
  4161.      *           MDB_FETCHMODE_ASSOC, FALSE, TRUE) returns:
  4162.      *    array(
  4163.      *      '1' => array(array('id' => '4', 'name' => 'number four'),
  4164.      *                   array('id' => '6', 'name' => 'number six')
  4165.      *             ),
  4166.      *      '9' => array(array('id' => '4', 'name' => 'number four'),
  4167.      *                   array('id' => '6', 'name' => 'number six')
  4168.      *             )
  4169.      *    )
  4170.      *
  4171.      * Keep in mind that database functions in PHP usually return string
  4172.      * values for results regardless of the database's internal type.
  4173.      *
  4174.      * @param string $query the SQL query
  4175.      * @param array $types array that contains the types of the columns in
  4176.      *       the result set
  4177.      * @param array $params array if supplied, prepare/execute will be used
  4178.      *       with this array as execute parameters
  4179.      * @param array $param_types array that contains the types of the values
  4180.      *       defined in $params
  4181.      * @param boolean $force_array used only when the query returns
  4182.      * exactly two columns.  If TRUE, the values of the returned array
  4183.      * will be one-element arrays instead of scalars.
  4184.      * @param boolean $group if TRUE, the values of the returned array
  4185.      *       is wrapped in another array.  If the same key value (in the first
  4186.      *       column) repeats itself, the values will be appended to this array
  4187.      *       instead of overwriting the existing values.
  4188.      * @return array associative array with results from the query.
  4189.      * @access public
  4190.      */
  4191.     function getAssoc($query, $types = NULL, $params = array(), $param_types = NULL,
  4192.         $fetchmode = MDB_FETCHMODE_ORDERED, $force_array = FALSE, $group = FALSE)
  4193.     {
  4194.         settype($params, 'array');
  4195.         if (count($params) > 0) {
  4196.             $prepared_query = $this->prepareQuery($query);
  4197.  
  4198.             if (MDB::isError($prepared_query)) {
  4199.                 return($prepared_query);
  4200.             }
  4201.             $this->setParamArray($prepared_query, $params, $param_types);
  4202.             $result = $this->executeQuery($prepared_query, $types);
  4203.         } else {
  4204.             $result = $this->query($query, $types);
  4205.         }
  4206.  
  4207.         if (MDB::isError($result)) {
  4208.             return($result);
  4209.         }
  4210.  
  4211.         $all = $this->fetchAll($result, $fetchmode, TRUE, $force_array, $group);
  4212.         if (MDB::isError($all)) {
  4213.             return($all);
  4214.         }
  4215.         if (isset($prepared_query)) {
  4216.             $result = $this->freePreparedQuery($prepared_query);
  4217.             if (MDB::isError($result)) {
  4218.                 return($result);
  4219.             }
  4220.         }
  4221.         return($all);
  4222.     }
  4223.  
  4224.     // }}}
  4225.     // {{{ getAll()
  4226.  
  4227.     /**
  4228.      * Fetch all the rows returned from a query.
  4229.      *
  4230.      * @param string $query the SQL query
  4231.      * @param array $types array that contains the types of the columns in
  4232.      *       the result set
  4233.      * @param array $params array if supplied, prepare/execute will be used
  4234.      *       with this array as execute parameters
  4235.      * @param array $param_types array that contains the types of the values
  4236.      *       defined in $params
  4237.      * @param integer $fetchmode the fetch mode to use
  4238.      * @return array an nested array, or a MDB error
  4239.      * @access public
  4240.      */
  4241.     function getAll($query, $types = NULL, $params = array(), $param_types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT)
  4242.     {
  4243.         settype($params, 'array');
  4244.         if (count($params) > 0) {
  4245.             $prepared_query = $this->prepareQuery($query);
  4246.  
  4247.             if (MDB::isError($prepared_query)) {
  4248.                 return($prepared_query);
  4249.             }
  4250.             $this->setParamArray($prepared_query, $params, $param_types);
  4251.             $result = $this->executeQuery($prepared_query, $types);
  4252.         } else {
  4253.             $result = $this->query($query, $types);
  4254.         }
  4255.  
  4256.         if (MDB::isError($result)) {
  4257.             return($result);
  4258.         }
  4259.  
  4260.         $all = $this->fetchAll($result, $fetchmode);
  4261.         if (MDB::isError($all)) {
  4262.             return($all);
  4263.         }
  4264.         if (isset($prepared_query)) {
  4265.             $result = $this->freePreparedQuery($prepared_query);
  4266.             if (MDB::isError($result)) {
  4267.                 return($result);
  4268.             }
  4269.         }
  4270.         return($all);
  4271.     }
  4272.  
  4273.     // }}}
  4274.     // {{{ tableInfo()
  4275.  
  4276.     /**
  4277.      * returns meta data about the result set
  4278.      *
  4279.      * @param resource $result result identifier
  4280.      * @param mixed $mode depends on implementation
  4281.      * @return array an nested array, or a MDB error
  4282.      * @access public
  4283.      */
  4284.     function tableInfo($result, $mode = NULL)
  4285.     {
  4286.         return($this->raiseError(MDB_ERROR_NOT_CAPABLE));
  4287.     }
  4288.  
  4289.     // }}}
  4290.     // {{{ createLob()
  4291.  
  4292.     /**
  4293.      * Create a handler object of a specified class with functions to
  4294.      * retrieve data from a large object data stream.
  4295.      *
  4296.      * @param array $arguments An associative array with parameters to create
  4297.      *                  the handler object. The array indexes are the names of
  4298.      *                  the parameters and the array values are the respective
  4299.      *                  parameter values.
  4300.      *
  4301.      *                  Some parameters are specific of the class of each type
  4302.      *                  of handler object that is created. The following
  4303.      *                  parameters are common to all handler object classes:
  4304.      *
  4305.      *                  Type
  4306.      *
  4307.      *                      Name of the type of the built-in supported class
  4308.      *                      that will be used to create the handler object.
  4309.      *                      There are currently four built-in types of handler
  4310.      *                      object classes: data, resultlob, inputfile and
  4311.      *                      outputfile.
  4312.      *
  4313.      *                      The data handler class is the default class. It
  4314.      *                      simply reads data from a given data string.
  4315.      *
  4316.      *                      The resultlob handler class is meant to read data
  4317.      *                      from a large object retrieved from a query result.
  4318.      *                      This class is not used directly by applications.
  4319.      *
  4320.      *                      The inputfile handler class is meant to read data
  4321.      *                      from a file to use in prepared queries with large
  4322.      *                      object field parameters.
  4323.      *
  4324.      *                      The outputfile handler class is meant to write to
  4325.      *                      a file data from result columns with large object
  4326.      *                      fields. The functions to read from this type of
  4327.      *                      large object do not return any data. Instead, the
  4328.      *                      data is just written to the output file with the
  4329.      *                      data retrieved from a specified large object handle.
  4330.      *
  4331.      *                  Class
  4332.      *
  4333.      *                      Name of the class of the handler object that will be
  4334.      *                      created if the Type argument is not specified. This
  4335.      *                      argument should be used when you need to specify a
  4336.      *                      custom handler class.
  4337.      *
  4338.      *                  Database
  4339.      *
  4340.      *                      Database object as returned by MDB::connect.
  4341.      *                      This is an option argument needed by some handler
  4342.      *                      classes like resultlob.
  4343.      *
  4344.      *                  The following arguments are specific of the inputfile
  4345.      *                  handler class:
  4346.      *
  4347.      *                      File
  4348.      *
  4349.      *                          Integer handle value of a file already opened
  4350.      *                          for writing.
  4351.      *
  4352.      *                      FileName
  4353.      *
  4354.      *                          Name of a file to be opened for writing if the
  4355.      *                          File argument is not specified.
  4356.      *
  4357.      *                  The following arguments are specific of the outputfile
  4358.      *                  handler class:
  4359.      *
  4360.      *                      File
  4361.      *
  4362.      *                          Integer handle value of a file already opened
  4363.      *                          for writing.
  4364.      *
  4365.      *                      FileName
  4366.      *
  4367.      *                          Name of a file to be opened for writing if the
  4368.      *                          File argument is not specified.
  4369.      *
  4370.      *                      BufferLength
  4371.      *
  4372.      *                          Integer value that specifies the length of a
  4373.      *                          buffer that will be used to read from the
  4374.      *                          specified large object.
  4375.      *
  4376.      *                      LOB
  4377.      *
  4378.      *                          Integer handle value that specifies a large
  4379.      *                          object from which the data to be stored in the
  4380.      *                          output file will be written.
  4381.      *
  4382.      *                      Result
  4383.      *
  4384.      *                          Integer handle value as returned by the function
  4385.      *                          MDB::query() or MDB::executeQuery() that specifies
  4386.      *                          the result set that contains the large object value
  4387.      *                          to be retrieved. If the LOB argument is specified,
  4388.      *                          this argument is ignored.
  4389.      *
  4390.      *                      Row
  4391.      *
  4392.      *                          Integer value that specifies the number of the
  4393.      *                          row of the result set that contains the large
  4394.      *                          object value to be retrieved. If the LOB
  4395.      *                          argument is specified, this argument is ignored.
  4396.      *
  4397.      *                      Field
  4398.      *
  4399.      *                          Integer or string value that specifies the
  4400.      *                          number or the name of the column of the result
  4401.      *                          set that contains the large object value to be
  4402.      *                          retrieved. If the LOB argument is specified,
  4403.      *                          this argument is ignored.
  4404.      *
  4405.      *                      Binary
  4406.      *
  4407.      *                          Boolean value that specifies whether the large
  4408.      *                          object column to be retrieved is of binary type
  4409.      *                          (blob) or otherwise is of character type (clob).
  4410.      *                          If the LOB argument is specified, this argument
  4411.      *                          is ignored.
  4412.      *
  4413.      *                  The following argument is specific of the data
  4414.      *                  handler class:
  4415.      *
  4416.      *                  Data
  4417.      *
  4418.      *                      String of data that will be returned by the class
  4419.      *                      when it requested with the readLOB() method.
  4420.      *
  4421.      *                  The following argument is specific of the resultlob
  4422.      *                  handler class:
  4423.      *
  4424.      *                      ResultLOB
  4425.      *
  4426.      *                          Integer handle value of a large object result
  4427.      *                          row field.
  4428.      * @return integer handle value that should be passed as argument insubsequent
  4429.      * calls to functions that retrieve data from the large object input stream.
  4430.      * @access public
  4431.      */
  4432.     function createLob($arguments)
  4433.     {
  4434.         $result = $this->loadLob('Create LOB');
  4435.         if (MDB::isError($result)) {
  4436.             return($result);
  4437.         }
  4438.         $class_name = 'MDB_LOB';
  4439.         if (isset($arguments['Type'])) {
  4440.             switch ($arguments['Type']) {
  4441.                 case 'data':
  4442.                     break;
  4443.                 case 'resultlob':
  4444.                     $class_name = 'MDB_LOB_Result';
  4445.                     break;
  4446.                 case 'inputfile':
  4447.                     $class_name = 'MDB_LOB_Input_File';
  4448.                     break;
  4449.                 case 'outputfile':
  4450.                     $class_name = 'MDB_LOB_Output_File';
  4451.                     break;
  4452.                 default:
  4453.                     if (isset($arguments['Error'])) {
  4454.                         $arguments['Error'] = $arguments['Type'] . ' is not a valid type of large object';
  4455.                     }
  4456.                     return($this->raiseError());
  4457.             }
  4458.         } else {
  4459.             if (isset($arguments['Class'])) {
  4460.                 $class = $arguments['Class'];
  4461.             }
  4462.         }
  4463.         $lob = count($GLOBALS['_MDB_lobs']) + 1;
  4464.         $GLOBALS['_MDB_lobs'][$lob] = &new $class_name;
  4465.         if (isset($arguments['Database'])) {
  4466.             $GLOBALS['_MDB_lobs'][$lob]->database = $arguments['Database'];
  4467.         } else {
  4468.             $GLOBALS['_MDB_lobs'][$lob]->database = &$this;
  4469.         }
  4470.         if (MDB::isError($result = $GLOBALS['_MDB_lobs'][$lob]->create($arguments))) {
  4471.             $GLOBALS['_MDB_lobs'][$lob]->database->destroyLob($lob);
  4472.             return($result);
  4473.         }
  4474.         return($lob);
  4475.     }
  4476.  
  4477.     // }}}
  4478.     // {{{ readLob()
  4479.  
  4480.     /**
  4481.      * Read data from large object input stream.
  4482.      *
  4483.      * @param integer $lob argument handle that is returned by the
  4484.      *                          MDB::createLob() method.
  4485.      * @param string $data reference to a variable that will hold data
  4486.      *                          to be read from the large object input stream
  4487.      * @param integer $length    value that indicates the largest ammount ofdata
  4488.      *                          to be read from the large object input stream.
  4489.      * @return mixed the effective number of bytes read from the large object
  4490.      *                      input stream on sucess or an MDB error object.
  4491.      * @access public
  4492.      * @see endOfLob()
  4493.      */
  4494.     function readLob($lob, &$data, $length)
  4495.     {
  4496.         return($GLOBALS['_MDB_lobs'][$lob]->readLob($data, $length));
  4497.     }
  4498.  
  4499.     // }}}
  4500.     // {{{ endOfLob()
  4501.  
  4502.     /**
  4503.      * Determine whether it was reached the end of the large object and
  4504.      * therefore there is no more data to be read for the its input stream.
  4505.      *
  4506.      * @param integer $lob argument handle that is returned by the
  4507.      *                          MDB::createLob() method.
  4508.      * @access public
  4509.      * @return boolean flag that indicates whether it was reached the end of the large object input stream
  4510.      */
  4511.     function endOfLob($lob)
  4512.     {
  4513.         return($GLOBALS['_MDB_lobs'][$lob]->endOfLob());
  4514.     }
  4515.  
  4516.     // }}}
  4517.     // {{{ destroyLob()
  4518.  
  4519.     /**
  4520.      * Free any resources allocated during the lifetime of the large object
  4521.      * handler object.
  4522.      *
  4523.      * @param integer $lob argument handle that is returned by the
  4524.      *                          MDB::createLob() method.
  4525.      * @access public
  4526.      */
  4527.     function destroyLob($lob)
  4528.     {
  4529.         $GLOBALS['_MDB_lobs'][$lob]->destroy();
  4530.         unset($GLOBALS['_MDB_lobs'][$lob]);
  4531.     }
  4532.  
  4533.     // }}}
  4534.     // {{{ Destructor
  4535.  
  4536.     /**
  4537.     * this function closes open transactions to be executed at shutdown
  4538.     *
  4539.     * @access private
  4540.     */
  4541.     function _MDB_Common()
  4542.     {
  4543.         if ($this->in_transaction && !MDB::isError($this->rollback())) {
  4544.             $this->autoCommit(TRUE);
  4545.         }
  4546.     }
  4547. };
  4548. ?>
  4549.