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

Source for file oci8.php

Documentation is available at oci8.php

  1. <?php
  2. // vim: set et ts=4 sw=4 fdm=marker:
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  7. // | Stig. S. Bakken, Lukas Smith                                         |
  8. // | All rights reserved.                                                 |
  9. // +----------------------------------------------------------------------+
  10. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
  11. // | API as well as database abstraction for PHP applications.            |
  12. // | This LICENSE is in the BSD license style.                            |
  13. // |                                                                      |
  14. // | Redistribution and use in source and binary forms, with or without   |
  15. // | modification, are permitted provided that the following conditions   |
  16. // | are met:                                                             |
  17. // |                                                                      |
  18. // | Redistributions of source code must retain the above copyright       |
  19. // | notice, this list of conditions and the following disclaimer.        |
  20. // |                                                                      |
  21. // | Redistributions in binary form must reproduce the above copyright    |
  22. // | notice, this list of conditions and the following disclaimer in the  |
  23. // | documentation and/or other materials provided with the distribution. |
  24. // |                                                                      |
  25. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  26. // | Lukas Smith nor the names of his contributors may be used to endorse |
  27. // | or promote products derived from this software without specific prior|
  28. // | written permission.                                                  |
  29. // |                                                                      |
  30. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  31. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  32. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  33. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  34. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  35. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  36. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  37. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  38. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  39. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  40. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  41. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  42. // +----------------------------------------------------------------------+
  43. // | Author: Lukas Smith <smith@backendmedia.com>                         |
  44. // +----------------------------------------------------------------------+
  45.  
  46. // $Id: oci8.php,v 1.11 2004/04/23 17:06:46 lsmith Exp $
  47.  
  48. /**
  49.  * MDB2 OCI8 driver
  50.  *
  51.  * @package MDB2
  52.  * @category Database
  53.  * @author Lukas Smith <smith@backendmedia.com>
  54.  */
  55. {
  56.     // {{{ properties
  57.     var $escape_quotes = "'";
  58.  
  59.     var $uncommitedqueries = 0;
  60.  
  61.     // }}}
  62.     // {{{ constructor
  63.  
  64.     /**
  65.      * Constructor
  66.      */
  67.     function MDB2_Driver_oci8()
  68.     {
  69.         $this->MDB2_Driver_Common();
  70.         $this->phptype 'oci8';
  71.         $this->dbsyntax 'oci8';
  72.  
  73.         $this->supported['sequences'= true;
  74.         $this->supported['indexes'= true;
  75.         $this->supported['summary_functions'= true;
  76.         $this->supported['order_by_text'= true;
  77.         $this->supported['current_id'= true;
  78.         $this->supported['affected_rows'= true;
  79.         $this->supported['transactions'= true;
  80.         $this->supported['limit_queries'= true;
  81.         $this->supported['LOBs'= true;
  82.         $this->supported['replace'= true;
  83.         $this->supported['sub_selects'= true;
  84.  
  85.         $this->options['DBA_username'= false;
  86.         $this->options['DBA_password'= false;
  87.         $this->options['database_name_prefix'= false;
  88.         $this->options['default_tablespace'= false;
  89.         $this->options['HOME'= false;
  90.         $this->options['default_text_field_length'= 4000;
  91.     }
  92.  
  93.     // }}}
  94.     // {{{ errorInfo()
  95.  
  96.     /**
  97.      * This method is used to collect information about an error
  98.      *
  99.      * @param integer $error 
  100.      * @return array 
  101.      * @access public
  102.      */
  103.     function errorInfo($error = null)
  104.     {
  105.         if (is_resource($error)) {
  106.             $error_data @OCIError($error);
  107.             $error = null;
  108.         else {
  109.             $error_data @OCIError($this->connection);
  110.         }
  111.         $native_code $error_data['code'];
  112.         $native_msg  $error_data['message'];
  113.         if (is_null($error)) {
  114.             static $ecode_map;
  115.             if (empty($ecode_map)) {
  116.                 $ecode_map = array(
  117.                     900 => MDB2_ERROR_SYNTAX,
  118.                     904 => MDB2_ERROR_NOSUCHFIELD,
  119.                     921 => MDB2_ERROR_SYNTAX,
  120.                     923 => MDB2_ERROR_SYNTAX,
  121.                     942 => MDB2_ERROR_NOSUCHTABLE,
  122.                     955 => MDB2_ERROR_ALREADY_EXISTS,
  123.                     1476 => MDB2_ERROR_DIVZERO,
  124.                     1722 => MDB2_ERROR_INVALID_NUMBER,
  125.                     2289 => MDB2_ERROR_NOSUCHTABLE,
  126.                     2291 => MDB2_ERROR_CONSTRAINT,
  127.                     2449 => MDB2_ERROR_CONSTRAINT,
  128.                 );
  129.             }
  130.             if (isset($ecode_map[$native_code])) {
  131.                 $error $ecode_map[$native_code];
  132.             }
  133.         }
  134.         return array($error$native_code$native_msg);
  135.     }
  136.  
  137.     // }}}
  138.     // {{{ autoCommit()
  139.  
  140.     /**
  141.      * Define whether database changes done on the database be automatically
  142.      * committed. This function may also implicitly start or end a transaction.
  143.      *
  144.      * @param boolean $auto_commit flag that indicates whether the database
  145.      *                                  changes should be committed right after
  146.      *                                  executing every query statement. If this
  147.      *                                  argument is 0 a transaction implicitly
  148.      *                                  started. Otherwise, if a transaction is
  149.      *                                  in progress it is ended by committing any
  150.      *                                  database changes that were pending.
  151.      * @access public
  152.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  153.      */
  154.     function autoCommit($auto_commit)
  155.     {
  156.         $this->debug(($auto_commit 'On' 'Off')'autoCommit');
  157.         if ($this->auto_commit == $auto_commit{
  158.             return MDB2_OK;
  159.         }
  160.         if ($this->connection && $auto_commit && MDB2::isError($commit $this->commit())) {
  161.             return $commit;
  162.         }
  163.         $this->auto_commit = $auto_commit;
  164.         $this->in_transaction !$auto_commit;
  165.         return MDB2_OK;
  166.     }
  167.  
  168.     // }}}
  169.     // {{{ commit()
  170.  
  171.     /**
  172.      * Commit the database changes done during a transaction that is in
  173.      * progress. This function may only be called when auto-committing is
  174.      * disabled, otherwise it will fail. Therefore, a new transaction is
  175.      * implicitly started after committing the pending changes.
  176.      *
  177.      * @access public
  178.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  179.      */
  180.     function commit()
  181.     {
  182.         $this->debug('commit transaction''commit');
  183.         if (!isset($this->supported['transactions'])) {
  184.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  185.                 'commit: transactions are not in use');
  186.         }
  187.         if ($this->auto_commit{
  188.             return $this->raiseError(MDB2_ERRORnullnull,
  189.             'commit: transaction changes are being auto commited');
  190.         }
  191.         if ($this->uncommitedqueries{
  192.             if (!@OCICommit($this->connection)) {
  193.                 return $this->raiseError();
  194.             }
  195.             $this->uncommitedqueries = 0;
  196.         }
  197.         return MDB2_OK;
  198.     }
  199.  
  200.     // }}}
  201.     // {{{ rollback()
  202.  
  203.     /**
  204.      * Cancel any database changes done during a transaction that is in
  205.      * progress. This function may only be called when auto-committing is
  206.      * disabled, otherwise it will fail. Therefore, a new transaction is
  207.      * implicitly started after canceling the pending changes.
  208.      *
  209.      * @access public
  210.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  211.      */
  212.     function rollback()
  213.     {
  214.         $this->debug('rolling back transaction''rollback');
  215.         if ($this->auto_commit{
  216.             return $this->raiseError(MDB2_ERRORnullnull,
  217.                 'rollback: transactions can not be rolled back when changes are auto commited');
  218.         }
  219.         if ($this->uncommitedqueries{
  220.             if (!@OCIRollback($this->connection)) {
  221.                 return $this->raiseError();
  222.             }
  223.             $this->uncommitedqueries = 0;
  224.         }
  225.         return MDB2_OK;
  226.     }
  227.  
  228.     // }}}
  229.     // {{{ _doConnect()
  230.  
  231.     /**
  232.      * do the grunt work of the connect
  233.      *
  234.      * @return connection on success or MDB2 Error Object on failure
  235.      * @access private
  236.      */
  237.     function _doConnect($username$password$persistent = false)
  238.     {
  239.         if (!PEAR::loadExtension($this->phptype)) {
  240.             return $this->raiseError(MDB2_ERROR_NOT_FOUNDnullnull,
  241.                 'extension '.$this->phptype.' is not compiled into PHP');
  242.         }
  243.  
  244.         if (isset($this->dsn['hostspec'])) {
  245.             $sid $this->dsn['hostspec'];
  246.         else {
  247.             $sid getenv('ORACLE_SID');
  248.         }
  249.         if (empty($sid)) {
  250.             return $this->raiseError(MDB2_ERRORnullnull,
  251.                 'it was not specified a valid Oracle Service Identifier (SID)');
  252.         }
  253.  
  254.         if ($this->options['HOME']{
  255.             putenv('ORACLE_HOME='.$this->options['HOME']);
  256.         }
  257.         putenv('ORACLE_SID='.$sid);
  258.         $function ($persistent 'OCIPLogon' 'OCINLogon');
  259.         $connection @$function($username$password$sid);
  260.         if (!$connection{
  261.             $connection =  $this->raiseError();
  262.         }
  263.         return $connection;
  264.     }
  265.  
  266.     // }}}
  267.     // {{{ connect()
  268.  
  269.     /**
  270.      * Connect to the database
  271.      *
  272.      * @return MDB2_OK on success, MDB2 Error Object on failure
  273.      * @access public
  274.      */
  275.     function connect()
  276.     {
  277.         if ($this->connection != 0{
  278.             if (count(array_diff($this->connected_dsn$this->dsn)) == 0
  279.                 && $this->opened_persistent == $this->options['persistent'])
  280.             {
  281.                 return MDB2_OK;
  282.             }
  283.             $this->_close();
  284.         }
  285.  
  286.         if ($this->database_name{
  287.             $database_name $this->options['database_name_prefix'].$this->database_name;
  288.             $connection $this->_doConnect($database_name$this->dsn['password']$this->options['persistent']);
  289.             if (MDB2::isError($connection)) {
  290.                 return $connection;
  291.             }
  292.             $this->connection $connection;
  293.             $this->connected_dsn $this->dsn;
  294.             $this->opened_persistent $this->options['persistent'];
  295.             $query "ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'";
  296.             $doquery $this->_doQuery($query);
  297.             if (MDB2::isError($doquery)) {
  298.                 $this->_close();
  299.                 return $doquery;
  300.             }
  301.             $query "ALTER SESSION SET NLS_NUMERIC_CHARACTERS='. '";
  302.             $doquery $this->_doQuery($query);
  303.             if (MDB2::isError($doquery)) {
  304.                 $this->_close();
  305.                 return $doquery;
  306.             }
  307.         }
  308.         return MDB2_OK;
  309.     }
  310.  
  311.     // }}}
  312.     // {{{ _close()
  313.     /**
  314.      * Close the database connection
  315.      *
  316.      * @return boolean 
  317.      * @access private
  318.      ***/
  319.     function _close()
  320.     {
  321.         if ($this->connection != 0{
  322.             if (!$this->auto_commit{
  323.                 $result $this->autoCommit(true);
  324.             }
  325.  
  326.             @OCILogOff($this->connection);
  327.             $this->connection = 0;
  328.             $this->affected_rows = -1;
  329.             $this->uncommitedqueries = 0;
  330.             unset($GLOBALS['_MDB2_databases'][$this->db_index]);
  331.  
  332.             if (isset($result&& MDB2::isError($result)) {
  333.                 return $result;
  334.             }
  335.         }
  336.         return MDB2_OK;
  337.     }
  338.  
  339.     // }}}
  340.     // {{{ _modifyQuery()
  341.  
  342.     /**
  343.      * This method is used by backends to alter queries for various
  344.      * reasons.
  345.      *
  346.      * @param string $query  query to modify
  347.      * @return the new (modified) query
  348.      * @access private
  349.      */
  350.     function _modifyQuery($query)
  351.     {
  352.         // "SELECT 2+2" must be "SELECT 2+2 FROM dual" in Oracle
  353.         if (preg_match('/^\s*SELECT/i'$query)
  354.             && !preg_match('/\sFROM\s/i'$query)
  355.         {
  356.             $query .= " FROM dual";
  357.         }
  358.         return $query;
  359.     }
  360.  
  361.     // }}}
  362.     // {{{ _doQuery()
  363.  
  364.     /**
  365.      * Execute a query
  366.      * @param string $query the SQL query
  367.      * @return mixed result identifier if query executed, else MDB2_error
  368.      * @access private
  369.      ***/
  370.     function _doQuery($query$ismanip = null$prepared_query = 0)
  371.     {
  372.         $lobs = 0;
  373.         $success MDB2_OK;
  374.         $result = 0;
  375.         $descriptors = array();
  376.  
  377.         if ($prepared_query{
  378.             $columns '';
  379.             $variables '';
  380.             for (reset($this->clobs[$prepared_query])$clob = 0;
  381.                 $clob count($this->clobs[$prepared_query]);
  382.                 $clob++next($this->clobs[$prepared_query])
  383.             {
  384.                 $clob_stream key($this->clobs[$prepared_query]);
  385.                 $descriptors[$clob_stream@OCINewDescriptor($this->connectionOCI_D_LOB);
  386.                 if (!is_object($descriptors[$clob_stream])) {
  387.                     $success $this->raiseError(MDB2_ERRORnullnull,
  388.                         'Could not create descriptor for clob parameter');
  389.                     break;
  390.                 }
  391.                 $parameter $GLOBALS['_MDB2_LOBs'][$clob_stream]->parameter;
  392.                 $columns.= ($lobs == 0 ? ' RETURNING ' ',').
  393.                     $this->prepared_queries[$prepared_query-1]['fields'][$parameter-1];
  394.                 $variables.= ($lobs == 0 ? ' INTO ' ',').':clob'.$parameter;
  395.                 ++$lobs;
  396.             }
  397.             if (!MDB2::isError($success)) {
  398.                 for (reset($this->blobs[$prepared_query])$blob = 0;
  399.                     $blob count($this->blobs[$prepared_query]);
  400.                     $blob++next($this->blobs[$prepared_query])
  401.                 {
  402.                     $blob_stream key($this->blobs[$prepared_query]);
  403.                     $descriptors[$blob_stream@OCINewDescriptor($this->connectionOCI_D_LOB);
  404.                     if (!is_object($descriptors[$blob_stream])) {
  405.                         $success $this->raiseError(MDB2_ERRORnullnull,
  406.                             'Could not create descriptor for blob parameter');
  407.                         break;
  408.                     }
  409.                     $parameter $GLOBALS['_MDB2_LOBs'][$blob_stream]->parameter;
  410.                     $columns.= ($lobs == 0 ? ' RETURNING ' ',').
  411.                         $this->prepared_queries[$prepared_query-1]['fields'][$parameter-1];
  412.                     $variables.= ($lobs == 0 ? ' INTO ' ',').':blob'.$parameter;
  413.                     ++$lobs;
  414.                 }
  415.                 $query.= $columns.$variables;
  416.             }
  417.         }
  418.  
  419.         if (!MDB2::isError($success)) {
  420.             if (($statement @OCIParse($this->connection$query))) {
  421.                 if ($lobs{
  422.                     for (reset($this->clobs[$prepared_query])$clob = 0;
  423.                         $clob count($this->clobs[$prepared_query]);
  424.                         $clob++next($this->clobs[$prepared_query])
  425.                     {
  426.                         $clob_stream key($this->clobs[$prepared_query]);
  427.                         $parameter $GLOBALS['_MDB2_LOBs'][$clob_stream]->parameter;
  428.                         if (!OCIBindByName($statement':clob'.$parameter$descriptors[$clob_stream]-1OCI_B_CLOB)) {
  429.                             $success $this->raiseError();
  430.                             break;
  431.                         }
  432.                     }
  433.                     if (!MDB2::isError($success)) {
  434.                         for (reset($this->blobs[$prepared_query])$blob = 0;
  435.                             $blob count($this->blobs[$prepared_query]);
  436.                             $blob++next($this->blobs[$prepared_query])
  437.                         {
  438.                             $blob_stream key($this->blobs[$prepared_query]);
  439.                             $parameter $GLOBALS['_MDB2_LOBs'][$blob_stream]->parameter;
  440.                             if (!OCIBindByName($statement':blob'.$parameter$descriptors[$blob_stream]-1OCI_B_BLOB)) {
  441.                                 $success $this->raiseError();
  442.                                 break;
  443.                             }
  444.                         }
  445.                     }
  446.                 }
  447.                 if (!MDB2::isError($success)) {
  448.                     $mode ($lobs == 0 && $this->auto_commit? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT;
  449.                     $result @OCIExecute($statement$mode);
  450.                     if ($result{
  451.                         if ($lobs{
  452.                             for (reset($this->clobs[$prepared_query])$clob = 0;
  453.                                 $clob count($this->clobs[$prepared_query]);
  454.                                 $clob++next($this->clobs[$prepared_query])
  455.                             {
  456.                                 $clob_stream key($this->clobs[$prepared_query]);
  457.                                 for ($value ''!$this->datatype->endOfLOB($clob_stream);{
  458.                                     if ($this->datatype->readLOB($clob_stream$data$this->options['lob_buffer_length']< 0{
  459.                                         $success $this->raiseError();
  460.                                         break;
  461.                                     }
  462.                                     $value.= $data;
  463.                                 }
  464.                                 if (!MDB2::isError($success&& !$descriptors[$clob_stream]->save($value)) {
  465.                                     $success $this->raiseError();
  466.                                 }
  467.                             }
  468.                             if (!MDB2::isError($success)) {
  469.                                 for (reset($this->blobs[$prepared_query])$blob = 0;
  470.                                     $blob count($this->blobs[$prepared_query]);
  471.                                     $blob++next($this->blobs[$prepared_query])
  472.                                 {
  473.                                     $blob_stream key($this->blobs[$prepared_query]);
  474.                                     for ($value ''!$this->datatype->endOfLOB($blob_stream);{
  475.                                         if ($this->datatype->readLOB($blob_stream$data$this->options['lob_buffer_length']< 0{
  476.                                             $success $this->raiseError();
  477.                                             break;
  478.                                         }
  479.                                         $value.= $data;
  480.                                     }
  481.                                     if (!MDB2::isError($success&& !$descriptors[$blob_stream]->save($value)) {
  482.                                         $success $this->raiseError();
  483.                                     }
  484.                                 }
  485.                             }
  486.                         }
  487.                         if ($this->auto_commit{
  488.                             if ($lobs{
  489.                                 if (MDB2::isError($success)) {
  490.                                     if (!OCIRollback($this->connection)) {
  491.                                         $success $this->raiseError();
  492.                                     }
  493.                                 else {
  494.                                     if (!OCICommit($this->connection)) {
  495.                                         $success $this->raiseError();
  496.                                     }
  497.                                 }
  498.                             }
  499.                         else {
  500.                             ++$this->uncommitedqueries;
  501.                         }
  502.                         if (!MDB2::isError($success)) {
  503.                             if (is_null($ismanip)) {
  504.                                 $ismanip MDB2::isManip($query);
  505.                             }
  506.                             if ($ismanip{
  507.                                 $this->affected_rows @OCIRowCount($statement);
  508.                                 @OCIFreeCursor($statement);
  509.                             }
  510.                             $result $statement;
  511.                         }
  512.                     else {
  513.                         return $this->raiseError($statement);
  514.                     }
  515.                 }
  516.             else {
  517.                 return $this->raiseError();
  518.             }
  519.         }
  520.         for (reset($descriptors)$descriptor = 0;
  521.             $descriptor count($descriptors);
  522.             $descriptor++next($descriptors)
  523.         {
  524.             @$descriptors[key($descriptors)]->free();
  525.         }
  526.         if (MDB2::isError($success)) {
  527.             return $success;
  528.         }
  529.         return $result;
  530.     }
  531.  
  532.     // }}}
  533.     // {{{ standaloneQuery()
  534.  
  535.    /**
  536.      * execute a query as DBA
  537.      *
  538.      * @param string $query the SQL query
  539.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  540.      * @access public
  541.      */
  542.     function standaloneQuery($query)
  543.     {
  544.         $connection $this->_doConnect($this->options['DBA_username']$this->options['DBA_password']$this->options['persistent']);
  545.         if (MDB2::isError($connection)) {
  546.             return $connection;
  547.         }
  548.         $result @OCIParse($connection$query);
  549.         if (!$result{
  550.             return $this->raiseError($connection);
  551.         }
  552.         if ($this->auto_commit{
  553.             $success @OCIExecute($resultOCI_COMMIT_ON_SUCCESS);
  554.         else {
  555.             $success @OCIExecute($resultOCI_DEFAULT);
  556.         }
  557.         if (!$success{
  558.             return $this->raiseError($result);
  559.         }
  560.         @OCILogOff($connection);
  561.         return MDB2_OK;
  562.     }
  563.  
  564.     // }}}
  565.     // {{{ _executePrepared()
  566.  
  567.     /**
  568.      * Execute a prepared query statement.
  569.      *
  570.      * @param int $prepared_query argument is a handle that was returned by
  571.      *        the function prepare()
  572.      * @param string $query query to be executed
  573.      * @param array $types array that contains the types of the columns in the result set
  574.      * @param mixed $result_class string which specifies which result class to use
  575.      * @param mixed $result_wrap_class string which specifies which class to wrap results in
  576.      * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
  577.      *
  578.      * @access private
  579.      */
  580.     function &_executePrepared($prepared_query$query$types = null,
  581.         $result_class = false$result_wrap_class = false)
  582.     {
  583.         $ismanip MDB2::isManip($query);
  584.         $offset $this->row_offset;
  585.         $limit $this->row_limit;
  586.         $this->row_offset $this->row_limit = 0;
  587.         $query $this->_modifyQuery($query);
  588.         $this->last_query = $query;
  589.         $this->debug($query'query');
  590.  
  591.         $connected $this->connect();
  592.         if (MDB2::isError($connected)) {
  593.             return $connected;
  594.         }
  595.  
  596.         $result $this->_doQuery($query$ismanip$prepared_query);
  597.         if (!MDB2::isError($result)) {
  598.             if ($ismanip{
  599.                 return MDB2_OK;
  600.             else {
  601.                 if (!$result_class{
  602.                     $result_class $this->options['result_buffering']
  603.                         ? $this->options['buffered_result_class'$this->options['result_class'];
  604.                 }
  605.                 $class_name sprintf($result_class$this->phptype);
  606.                 $result =new $class_name($this$result$offset$limit);
  607.                 if ($types{
  608.                     $err $result->setResultTypes($types);
  609.                     if (MDB2::isError($err)) {
  610.                         $result->free();
  611.                         return $err;
  612.                     }
  613.                 }
  614.                 if (!$result_wrap_class{
  615.                     $result_wrap_class $this->options['result_wrap_class'];
  616.                 }
  617.                 if ($result_wrap_class{
  618.                     $result =new $result_wrap_class($result);
  619.                 }
  620.                 return $result;
  621.             }
  622.         }
  623.         return $result;
  624.     }
  625.  
  626.     // }}}
  627.     // {{{ query()
  628.  
  629.     /**
  630.      * Send a query to the database and return any results
  631.      *
  632.      * @param string $query the SQL query
  633.      * @param array $types array that contains the types of the columns in the result set
  634.      * @param mixed $result_class string which specifies which result class to use
  635.      * @param mixed $result_wrap_class string which specifies which class to wrap results in
  636.      * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
  637.      *
  638.      * @access public
  639.      */
  640.     function &query($query$types = null$result_class = false$result_wrap_class = false)
  641.     {
  642.         $result =$this->_executePrepared(false$query$types$result_class$result_wrap_class);
  643.         return $result;
  644.     }
  645.  
  646.     // }}}
  647.     // {{{ nextID()
  648.  
  649.     /**
  650.      * returns the next free id of a sequence
  651.      *
  652.      * @param string $seq_name name of the sequence
  653.      * @param boolean $ondemand when true the seqence is
  654.      *                            automatic created, if it
  655.      *                            not exists
  656.      * @return mixed MDB2 Error Object or id
  657.      * @access public
  658.      */
  659.     function nextID($seq_name$ondemand = true)
  660.     {
  661.         $sequence_name $this->getSequenceName($seq_name);
  662.         $this->expectError(MDB2_ERROR_NOSUCHTABLE);
  663.         $result $this->queryOne("SELECT $sequence_name.nextval FROM DUAL");
  664.         $this->popExpect();
  665.         if (MDB2::isError($result)) {
  666.             if ($ondemand && $result->getCode(== MDB2_ERROR_NOSUCHTABLE{
  667.                 $this->loadModule('manager');
  668.                 $result $this->manager->createSequence($seq_name1);
  669.                 if (MDB2::isError($result)) {
  670.                     return $result;
  671.                 }
  672.                 return $this->nextId($seq_namefalse);
  673.             }
  674.         }
  675.         return $result;
  676.     }
  677.  
  678.     // }}}
  679.     // {{{ currId()
  680.  
  681.     /**
  682.      * returns the current id of a sequence
  683.      *
  684.      * @param string $seq_name name of the sequence
  685.      * @return mixed MDB2_Error or id
  686.      * @access public
  687.      */
  688.     function currId($seq_name)
  689.     {
  690.         $sequence_name $this->getSequenceName($seq_name);
  691.         return $this->queryOne("SELECT $sequence_name.currval FROM DUAL");
  692.     }
  693. }
  694.  
  695. class MDB2_Result_oci8 extends MDB2_Result_Common
  696. {
  697.     var $limits;
  698.  
  699.     // }}}
  700.     // {{{ constructor
  701.  
  702.     /**
  703.      * Constructor
  704.      */
  705.     function MDB2_Result_oci8(&$mdb&$result$offset$limit)
  706.     {
  707.         parent::MDB2_Result_Common($mdb$result);
  708.         if ($offset || $limit{
  709.             $this->limits = array(
  710.                 'offset' => $offset,
  711.                 'count' => 0,
  712.                 'limit' => ($limit - 1),
  713.             );
  714.         }
  715.     }
  716.  
  717.     // }}}
  718.     // {{{ _skipLimitOffset()
  719.  
  720.     /**
  721.      * Skip the first row of a result set.
  722.      *
  723.      * @param resource $result 
  724.      * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
  725.      * @access private
  726.      */
  727.     function _skipLimitOffset()
  728.     {
  729.         if (isset($this->limits&& is_array($this->limits)) {
  730.             if ($this->rownum $this->limits['limit']{
  731.                 return false;
  732.             }
  733.             while ($this->limits['count'$this->limits['offset']{
  734.                 ++$this->limits['count'];
  735.                 if (!@OCIFetchInto($this->result$rowOCI_RETURN_NULLS)) {
  736.                     return false;
  737.                 }
  738.             }
  739.         }
  740.         return true;
  741.     }
  742.  
  743.     // }}}
  744.     // {{{ fetch()
  745.  
  746.     /**
  747.     * fetch value from a result set
  748.     *
  749.     * @param int    $rownum    number of the row where the data can be found
  750.     * @param int    $colnum    field number where the data can be found
  751.     * @return mixed string on success, a MDB2 error on failure
  752.     * @access public
  753.     */
  754.     function fetch($rownum = 0$colnum = 0)
  755.     {
  756.         $seek $this->seek($rownum);
  757.         if (MDB2::isError($seek)) {
  758.             return $seek;
  759.         }
  760.         $fetchmode is_numeric($colnumMDB2_FETCHMODE_ORDERED : MDB2_FETCHMODE_ASSOC;
  761.         $row $this->fetchRow($fetchmode);
  762.         if (!$row || MDB2::isError($row)) {
  763.             return $row;
  764.         }
  765.         if (!array_key_exists($colnum$row)) {
  766.             return null;
  767.         }
  768.         return $row[$colnum];
  769.     }
  770.  
  771.     // }}}
  772.     // {{{ fetchRow()
  773.  
  774.     /**
  775.      * Fetch a row and insert the data into an existing array.
  776.      *
  777.      * @param int       $fetchmode  how the array data should be indexed
  778.      * @return int data array on success, a MDB2 error on failure
  779.      * @access public
  780.      */
  781.     function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT)
  782.     {
  783.         if ($fetchmode == MDB2_FETCHMODE_DEFAULT{
  784.             $fetchmode $this->mdb->fetchmode;
  785.         }
  786.         if (!$this->_skipLimitOffset()) {
  787.             return null;
  788.         }
  789.         if ($fetchmode MDB2_FETCHMODE_ASSOC{
  790.             @OCIFetchInto($this->result$rowOCI_ASSOC+OCI_RETURN_NULLS);
  791.             if (is_array($row)
  792.                 && $this->mdb->options['portability'MDB2_PORTABILITY_LOWERCASE
  793.             {
  794.                 $row array_change_key_case($rowCASE_LOWER);
  795.             }
  796.         else {
  797.             @OCIFetchInto($this->result$rowOCI_RETURN_NULLS);
  798.         }
  799.         if (!$row{
  800.             if (is_null($this->result)) {
  801.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  802.                     'fetchRow: resultset has already been freed');
  803.             }
  804.             return null;
  805.         }
  806.         if (isset($this->types)) {
  807.             $row $this->mdb->datatype->convertResultRow($this->types$row);
  808.         }
  809.         if ($this->mdb->options['portability'MDB2_PORTABILITY_RTRIM{
  810.             $this->mdb->_rtrimArrayValues($row);
  811.         }
  812.         ++$this->rownum;
  813.         return $row;
  814.     }
  815.  
  816.     // }}}
  817.     // {{{ getColumnNames()
  818.  
  819.     /**
  820.      * Retrieve the names of columns returned by the DBMS in a query result.
  821.      *
  822.      * @return mixed associative array variable
  823.      *       that holds the names of columns. The indexes of the array are
  824.      *       the column names mapped to lower case and the values are the
  825.      *       respective numbers of the columns starting from 0. Some DBMS may
  826.      *       not return any columns when the result set does not contain any
  827.      *       rows.
  828.      * @access public
  829.      */
  830.     function getColumnNames()
  831.     {
  832.         $columns = array();
  833.         $numcols $this->numCols();
  834.         if (MDB2::isError($numcols)) {
  835.             return $numcols;
  836.         }
  837.         for ($column = 0; $column $numcols$column++{
  838.             $column_name @OCIColumnName($this->result$column + 1);
  839.             $columns[$column_name$column;
  840.         }
  841.         if ($this->mdb->options['portability'MDB2_PORTABILITY_LOWERCASE{
  842.             $columns array_change_key_case($columnsCASE_LOWER);
  843.         }
  844.         return $columns;
  845.     }
  846.  
  847.     // }}}
  848.     // {{{ numCols()
  849.  
  850.     /**
  851.      * Count the number of columns returned by the DBMS in a query result.
  852.      *
  853.      * @return mixed integer value with the number of columns, a MDB2 error
  854.      *       on failure
  855.      * @access public
  856.      */
  857.     function numCols()
  858.     {
  859.         $cols @OCINumCols($this->result);
  860.         if (is_null($cols)) {
  861.             if (is_null($this->result)) {
  862.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  863.                     'numCols: resultset has already been freed');
  864.             }
  865.             return $this->mdb->raiseError();
  866.         }
  867.         return $cols;
  868.     }
  869.  
  870.     // }}}
  871.     // {{{ free()
  872.  
  873.     /**
  874.      * Free the internal resources associated with $result.
  875.      *
  876.      * @return boolean true on success, false if $result is invalid
  877.      * @access public
  878.      */
  879.     function free()
  880.     {
  881.         $free @OCIFreeCursor($this->result);
  882.         if (!$free{
  883.             if (is_null($this->result)) {
  884.                 return MDB2_OK;
  885.             }
  886.             return $this->mdb->raiseError();
  887.         }
  888.         $this->result = null;
  889.         return MDB2_OK;
  890.     }
  891. }
  892.  
  893. class MDB2_BufferedResult_oci8 extends MDB2_Result_oci8
  894. {
  895.     var $buffer;
  896.     var $buffer_rownum = - 1;
  897.  
  898.     // }}}
  899.     // {{{ constructor
  900.  
  901.     /**
  902.      * Constructor
  903.      */
  904.     function MDB2_BufferedResult_oci8(&$mdb&$result$offset$limit)
  905.     {
  906.         parent::MDB2_Result_oci8($mdb$result$offset$limit);
  907.     }
  908.  
  909.     // }}}
  910.     // {{{ _fillBuffer()
  911.  
  912.     /**
  913.      * Fill the row buffer
  914.      *
  915.      * @param int $rownum   row number upto which the buffer should be filled
  916.                             if the row number is null all rows are ready into the buffer
  917.      * @return boolean true on success, false on failure
  918.      * @access private
  919.      */
  920.     function _fillBuffer($rownum = null)
  921.     {
  922.         if (isset($this->buffer&& is_array($this->buffer)) {
  923.             if (is_null($rownum)) {
  924.                 if (!end($this->buffer)) {
  925.                     return false;
  926.                 }
  927.             else if (isset($this->buffer[$rownum])) {
  928.                 return (bool)$this->buffer[$rownum];
  929.             }
  930.         }
  931.  
  932.         if (!$this->_skipLimitOffset()) {
  933.             return false;
  934.         }
  935.  
  936.         $row = true;
  937.         while ((is_null($rownum|| $this->buffer_rownum $rownum)
  938.             && (!isset($this->limits|| $this->buffer_rownum $this->limits['limit'])
  939.             && ($row @OCIFetchInto($this->result$bufferOCI_RETURN_NULLS))
  940.         {
  941.             ++$this->buffer_rownum;
  942.             $this->buffer[$this->buffer_rownum$buffer;
  943.         }
  944.  
  945.         if (!$row{
  946.             ++$this->buffer_rownum;
  947.             $this->buffer[$this->buffer_rownum= false;
  948.             return false;
  949.         elseif (isset($this->limits&& $this->buffer_rownum >= $this->limits['limit']{
  950.             ++$this->buffer_rownum;
  951.             $this->buffer[$this->buffer_rownum= false;
  952.         }
  953.         return true;
  954.     }
  955.  
  956.     // }}}
  957.     // {{{ fetchRow()
  958.  
  959.     /**
  960.      * Fetch a row and insert the data into an existing array.
  961.      *
  962.      * @param int       $fetchmode  how the array data should be indexed
  963.      * @return int data array on success, a MDB2 error on failure
  964.      * @access public
  965.      */
  966.     function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT)
  967.     {
  968.         if (is_null($this->result)) {
  969.             return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  970.                 'fetchRow: resultset has already been freed');
  971.         }
  972.         $target_rownum $this->rownum + 1;
  973.         if ($fetchmode == MDB2_FETCHMODE_DEFAULT{
  974.             $fetchmode $this->mdb->fetchmode;
  975.         }
  976.         if (!$this->_fillBuffer($target_rownum)) {
  977.             return null;
  978.         }
  979.         $row $this->buffer[$target_rownum];
  980.         if ($fetchmode MDB2_FETCHMODE_ASSOC{
  981.             $column_names $this->getColumnNames();
  982.             foreach ($column_names as $name => $i{
  983.                 $column_names[$name$row[$i];
  984.             }
  985.             $row $column_names;
  986.         }
  987.         if (isset($this->types)) {
  988.             $row $this->mdb->datatype->convertResultRow($this->types$row);
  989.         }
  990.         if ($this->mdb->options['portability'MDB2_PORTABILITY_RTRIM{
  991.             $this->mdb->_rtrimArrayValues($row);
  992.         }
  993.         ++$this->rownum;
  994.         return $row;
  995.     }
  996.  
  997.     // }}}
  998.     // {{{ seek()
  999.  
  1000.     /**
  1001.     * seek to a specific row in a result set
  1002.     *
  1003.     * @param int    $rownum    number of the row where the data can be found
  1004.     * @return mixed MDB2_OK on success, a MDB2 error on failure
  1005.     * @access public
  1006.     */
  1007.     function seek($rownum = 0)
  1008.     {
  1009.         if (is_null($this->result)) {
  1010.             return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  1011.                 'seek: resultset has already been freed');
  1012.         }
  1013.         $this->rownum $rownum - 1;
  1014.         return MDB2_OK;
  1015.     }
  1016.  
  1017.     // }}}
  1018.     // {{{ valid()
  1019.  
  1020.     /**
  1021.      * check if the end of the result set has been reached
  1022.      *
  1023.      * @return mixed true or false on sucess, a MDB2 error on failure
  1024.      * @access public
  1025.      */
  1026.     function valid()
  1027.     {
  1028.         if (is_null($this->result)) {
  1029.             return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  1030.                 'valid: resultset has already been freed');
  1031.         }
  1032.         if ($this->_fillBuffer($this->rownum + 1)) {
  1033.             return true;
  1034.         }
  1035.         return false;
  1036.     }
  1037.  
  1038.     // }}}
  1039.     // {{{ numRows()
  1040.  
  1041.     /**
  1042.      * returns the number of rows in a result object
  1043.      *
  1044.      * @return mixed MDB2 Error Object or the number of rows
  1045.      * @access public
  1046.      */
  1047.     function numRows()
  1048.     {
  1049.         if (is_null($this->result)) {
  1050.             return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  1051.                 'seek: resultset has already been freed');
  1052.         }
  1053.         $this->_fillBuffer();
  1054.         return $this->buffer_rownum;
  1055.     }
  1056.  
  1057.     // }}}
  1058.     // {{{ free()
  1059.  
  1060.     /**
  1061.      * Free the internal resources associated with $result.
  1062.      *
  1063.      * @return boolean true on success, false if $result is invalid
  1064.      * @access public
  1065.      */
  1066.     function free()
  1067.     {
  1068.         $this->buffer = null;
  1069.         $this->buffer_rownum = null;
  1070.         $free = parent::free();
  1071.     }
  1072. }
  1073.  
  1074. ?>

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