PHPOpenChat PHP Cross Reference Customer Relationship Management

Source: /include/adodb/drivers/adodb-oci8.inc.php - 1394 lines - 41625 bytes - Summary - Text - Print

   1  <?php
   2  /*

   3  

   4    version V4.61 24 Feb 2005 (c) 2000-2005 John Lim. All rights reserved.

   5  

   6    Released under both BSD license and Lesser GPL library license. 

   7    Whenever there is any discrepancy between the two licenses, 

   8    the BSD license will take precedence.

   9  

  10    Latest version is available at http://adodb.sourceforge.net

  11    

  12    Code contributed by George Fourlanos <fou@infomap.gr>

  13    

  14    13 Nov 2000 jlim - removed all ora_* references.

  15  */
  16  
  17  // security - hide paths

  18  if (!defined('ADODB_DIR')) die();
  19  
  20  /*

  21  NLS_Date_Format

  22  Allows you to use a date format other than the Oracle Lite default. When a literal

  23  character string appears where a date value is expected, the Oracle Lite database

  24  tests the string to see if it matches the formats of Oracle, SQL-92, or the value

  25  specified for this parameter in the POLITE.INI file. Setting this parameter also

  26  defines the default format used in the TO_CHAR or TO_DATE functions when no

  27  other format string is supplied.

  28  

  29  For Oracle the default is dd-mon-yy or dd-mon-yyyy, and for SQL-92 the default is

  30  yy-mm-dd or yyyy-mm-dd.

  31  

  32  Using 'RR' in the format forces two-digit years less than or equal to 49 to be

  33  interpreted as years in the 21st century (20002049), and years over 50 as years in

  34  the 20th century (19501999). Setting the RR format as the default for all two-digit

  35  year entries allows you to become year-2000 compliant. For example:

  36  NLS_DATE_FORMAT='RR-MM-DD'

  37  

  38  You can also modify the date format using the ALTER SESSION command. 

  39  */
  40  
  41  # define the LOB descriptor type for the given type

  42  # returns false if no LOB descriptor

  43  function oci_lob_desc($type) {
  44      switch ($type) {
  45          case OCI_B_BFILE: $result = OCI_D_FILE; break;
  46          case OCI_B_CFILEE: $result = OCI_D_FILE; break;
  47          case OCI_B_CLOB: $result = OCI_D_LOB; break;
  48          case OCI_B_BLOB: $result = OCI_D_LOB; break;
  49          case OCI_B_ROWID: $result = OCI_D_ROWID; break;
  50          default: $result = false; break;
  51      }
  52      return $result;
  53  }
  54  
  55  class ADODB_oci8 extends ADOConnection {
  56      var $databaseType = 'oci8';
  57      var $dataProvider = 'oci8';
  58      var $replaceQuote = "''"; // string to use to replace quotes

  59      var $concat_operator='||';
  60      var $sysDate = "TRUNC(SYSDATE)";
  61      var $sysTimeStamp = 'SYSDATE';
  62      var $metaDatabasesSQL = "SELECT USERNAME FROM ALL_USERS WHERE USERNAME NOT IN ('SYS','SYSTEM','DBSNMP','OUTLN') ORDER BY 1";
  63      var $_stmt;
  64      var $_commit = OCI_COMMIT_ON_SUCCESS;
  65      var $_initdate = true; // init date to YYYY-MM-DD

  66      var $metaTablesSQL = "select table_name,table_type from cat where table_type in ('TABLE','VIEW')";
  67      var $metaColumnsSQL = "select cname,coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno"; //changed by smondino@users.sourceforge. net

  68      var $_bindInputArray = true;
  69      var $hasGenID = true;
  70      var $_genIDSQL = "SELECT (%s.nextval) FROM DUAL";
  71      var $_genSeqSQL = "CREATE SEQUENCE %s START WITH %s";
  72      var $_dropSeqSQL = "DROP SEQUENCE %s";
  73      var $hasAffectedRows = true;
  74      var $random = "abs(mod(DBMS_RANDOM.RANDOM,10000001)/10000000)";
  75      var $noNullStrings = false;
  76      var $connectSID = false;
  77      var $_bind = false;
  78      var $_hasOCIFetchStatement = false;
  79      var $_getarray = false; // currently not working

  80      var $leftOuter = '';  // oracle wierdness, $col = $value (+) for LEFT OUTER, $col (+)= $value for RIGHT OUTER

  81      var $session_sharing_force_blob = false; // alter session on updateblob if set to true 

  82      var $firstrows = true; // enable first rows optimization on SelectLimit()

  83      var $selectOffsetAlg1 = 100; // when to use 1st algorithm of selectlimit.

  84      var $NLS_DATE_FORMAT = 'YYYY-MM-DD';  // To include time, use 'RRRR-MM-DD HH24:MI:SS'

  85       var $useDBDateFormatForTextInput=false;
  86      var $datetime = false; // MetaType('DATE') returns 'D' (datetime==false) or 'T' (datetime == true)

  87      var $_refLOBs = array();
  88      
  89      // var $ansiOuter = true; // if oracle9

  90      
  91  	function ADODB_oci8() 
  92      {
  93          $this->_hasOCIFetchStatement = ADODB_PHPVER >= 0x4200;
  94          if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_';
  95      }
  96      
  97      /*  Function &MetaColumns($table) added by smondino@users.sourceforge.net*/

  98      function &MetaColumns($table) 
  99      {
 100      global $ADODB_FETCH_MODE;
 101      
 102          $false = false;
 103          $save = $ADODB_FETCH_MODE;
 104          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 105          if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
 106          
 107          $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
 108          
 109          if (isset($savem)) $this->SetFetchMode($savem);
 110          $ADODB_FETCH_MODE = $save;
 111          if (!$rs) {
 112              return $false;
 113          }
 114          $retarr = array();
 115          while (!$rs->EOF) { //print_r($rs->fields);
 116              $fld = new ADOFieldObject();
 117                 $fld->name = $rs->fields[0];
 118                 $fld->type = $rs->fields[1];
 119                 $fld->max_length = $rs->fields[2];
 120              $fld->scale = $rs->fields[3];
 121              if ($rs->fields[1] == 'NUMBER' && $rs->fields[3] == 0) {
 122                  $fld->type ='INT';
 123                   $fld->max_length = $rs->fields[4];
 124              }    
 125                 $fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0);
 126              $fld->binary = (strpos($fld->type,'BLOB') !== false);
 127              $fld->default_value = $rs->fields[6];
 128              
 129              if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;    
 130              else $retarr[strtoupper($fld->name)] = $fld;
 131              $rs->MoveNext();
 132          }
 133          $rs->Close();
 134          return (empty($retarr)) ? $false : $retarr;
 135      }
 136      
 137  	function Time()
 138      {
 139          $rs =& $this->Execute("select TO_CHAR($this->sysTimeStamp,'YYYY-MM-DD HH24:MI:SS') from dual");
 140          if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields));
 141          
 142          return false;
 143      }
 144   
 145  /*

 146  

 147    Multiple modes of connection are supported:

 148    

 149    a. Local Database

 150      $conn->Connect(false,'scott','tiger');

 151    

 152    b. From tnsnames.ora

 153      $conn->Connect(false,'scott','tiger',$tnsname); 

 154      $conn->Connect($tnsname,'scott','tiger'); 

 155    

 156    c. Server + service name

 157      $conn->Connect($serveraddress,'scott,'tiger',$service_name);

 158    

 159    d. Server + SID

 160        $conn->connectSID = true;

 161      $conn->Connect($serveraddress,'scott,'tiger',$SID);

 162  

 163  

 164  Example TNSName:

 165  ---------------

 166  NATSOFT.DOMAIN =

 167    (DESCRIPTION =

 168      (ADDRESS_LIST =

 169        (ADDRESS = (PROTOCOL = TCP)(HOST = kermit)(PORT = 1523))

 170      )

 171      (CONNECT_DATA =

 172        (SERVICE_NAME = natsoft.domain)

 173      )

 174    )

 175    

 176    There are 3 connection modes, 0 = non-persistent, 1 = persistent, 2 = force new connection

 177      

 178  */
 179  	function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$mode=0)
 180      {
 181          if (!function_exists('OCIPLogon')) return null;
 182          
 183          
 184          $this->_errorMsg = false;
 185          $this->_errorCode = false;
 186          
 187          if($argHostname) { // added by Jorma Tuomainen <jorma.tuomainen@ppoy.fi>
 188              if (empty($argDatabasename)) $argDatabasename = $argHostname;
 189              else {
 190                  if(strpos($argHostname,":")) {
 191                      $argHostinfo=explode(":",$argHostname);
 192                         $argHostname=$argHostinfo[0];
 193                      $argHostport=$argHostinfo[1];
 194                   } else {
 195                      $argHostport="1521";
 196                     }
 197                  
 198                  if ($this->connectSID) {
 199                      $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
 200                      .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))";
 201                  } else
 202                      $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
 203                      .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))";
 204              }
 205          }
 206                  
 207           //if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>";

 208          if ($mode==1) {
 209              $this->_connectionID = ($this->charSet) ? 
 210                  OCIPLogon($argUsername,$argPassword, $argDatabasename)
 211                  :
 212                  OCIPLogon($argUsername,$argPassword, $argDatabasename, $this->charSet)
 213                  ;
 214              if ($this->_connectionID && $this->autoRollback)  OCIrollback($this->_connectionID);
 215          } else if ($mode==2) {
 216              $this->_connectionID = ($this->charSet) ? 
 217                  OCINLogon($argUsername,$argPassword, $argDatabasename)
 218                  :
 219                  OCINLogon($argUsername,$argPassword, $argDatabasename, $this->charSet);
 220                  
 221          } else {
 222              $this->_connectionID = ($this->charSet) ? 
 223                  OCILogon($argUsername,$argPassword, $argDatabasename)
 224                  :
 225                  OCILogon($argUsername,$argPassword, $argDatabasename,$this->charSet);
 226          }
 227          if ($this->_connectionID === false) return false;
 228          if ($this->_initdate) {
 229              $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='".$this->NLS_DATE_FORMAT."'");
 230          }
 231          
 232          // looks like: 

 233          // Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production

 234          // $vers = OCIServerVersion($this->_connectionID);

 235          // if (strpos($vers,'8i') !== false) $this->ansiOuter = true;

 236          return true;
 237         }
 238      
 239  	function ServerInfo()
 240      {
 241          $arr['compat'] = $this->GetOne('select value from sys.database_compatible_level');
 242          $arr['description'] = @OCIServerVersion($this->_connectionID);
 243          $arr['version'] = ADOConnection::_findvers($arr['description']);
 244          return $arr;
 245      }
 246          // returns true or false

 247  	function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
 248      {
 249          return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,1);
 250      }
 251      
 252      // returns true or false

 253  	function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
 254      {
 255          return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,2);
 256      }
 257      
 258  	function _affectedrows()
 259      {
 260          if (is_resource($this->_stmt)) return @OCIRowCount($this->_stmt);
 261          return 0;
 262      }
 263      
 264  	function IfNull( $field, $ifNull ) 
 265      {
 266          return " NVL($field, $ifNull) "; // if Oracle

 267      }
 268      
 269      // format and return date string in database date format

 270  	function DBDate($d)
 271      {
 272          if (empty($d) && $d !== 0) return 'null';
 273          
 274          if (is_string($d)) $d = ADORecordSet::UnixDate($d);
 275          return "TO_DATE(".adodb_date($this->fmtDate,$d).",'".$this->NLS_DATE_FORMAT."')";
 276      }
 277  
 278      
 279      // format and return date string in database timestamp format

 280  	function DBTimeStamp($ts)
 281      {
 282          if (empty($ts) && $ts !== 0) return 'null';
 283          if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
 284          return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'RRRR-MM-DD, HH:MI:SS AM')";
 285      }
 286      
 287  	function RowLock($tables,$where) 
 288      {
 289          if ($this->autoCommit) $this->BeginTrans();
 290          return $this->GetOne("select 1 as ignore from $tables where $where for update");
 291      }
 292      
 293      function &MetaTables($ttype=false,$showSchema=false,$mask=false) 
 294      {
 295          if ($mask) {
 296              $save = $this->metaTablesSQL;
 297              $mask = $this->qstr(strtoupper($mask));
 298              $this->metaTablesSQL .= " AND table_name like $mask";
 299          }
 300          $ret =& ADOConnection::MetaTables($ttype,$showSchema);
 301          
 302          if ($mask) {
 303              $this->metaTablesSQL = $save;
 304          }
 305          return $ret;
 306      }
 307      
 308      // Mark Newnham 

 309      function &MetaIndexes ($table, $primary = FALSE, $owner=false)
 310      {
 311          // save old fetch mode

 312          global $ADODB_FETCH_MODE;
 313  
 314          $save = $ADODB_FETCH_MODE;
 315          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 316  
 317          if ($this->fetchMode !== FALSE) {
 318                 $savem = $this->SetFetchMode(FALSE);
 319          }
 320  
 321          // get index details

 322          $table = strtoupper($table);
 323  
 324          // get Primary index

 325          $primary_key = '';
 326  
 327          $false = false;
 328          $rs = $this->Execute(sprintf("SELECT * FROM ALL_CONSTRAINTS WHERE UPPER(TABLE_NAME)='%s' AND CONSTRAINT_TYPE='P'",$table));
 329          if ($row = $rs->FetchRow())
 330             $primary_key = $row[1]; //constraint_name

 331  
 332          if ($primary==TRUE && $primary_key=='') {
 333               if (isset($savem)) 
 334                  $this->SetFetchMode($savem);
 335              $ADODB_FETCH_MODE = $save;
 336              return $false; //There is no primary key

 337          }
 338  
 339          $rs = $this->Execute(sprintf("SELECT ALL_INDEXES.INDEX_NAME, ALL_INDEXES.UNIQUENESS, ALL_IND_COLUMNS.COLUMN_POSITION, ALL_IND_COLUMNS.COLUMN_NAME FROM ALL_INDEXES,ALL_IND_COLUMNS WHERE UPPER(ALL_INDEXES.TABLE_NAME)='%s' AND ALL_IND_COLUMNS.INDEX_NAME=ALL_INDEXES.INDEX_NAME",$table));
 340  
 341          
 342          if (!is_object($rs)) {
 343              if (isset($savem)) 
 344                  $this->SetFetchMode($savem);
 345              $ADODB_FETCH_MODE = $save;
 346              return $false;
 347          }
 348  
 349          $indexes = array ();
 350          // parse index data into array

 351  
 352          while ($row = $rs->FetchRow()) {
 353              if ($primary && $row[0] != $primary_key) continue;
 354              if (!isset($indexes[$row[0]])) {
 355                  $indexes[$row[0]] = array(
 356                     'unique' => ($row[1] == 'UNIQUE'),
 357                     'columns' => array()
 358                  );
 359              }
 360              $indexes[$row[0]]['columns'][$row[2] - 1] = $row[3];
 361          }
 362  
 363          // sort columns by order in the index

 364          foreach ( array_keys ($indexes) as $index ) {
 365              ksort ($indexes[$index]['columns']);
 366          }
 367  
 368          if (isset($savem)) { 
 369              $this->SetFetchMode($savem);
 370              $ADODB_FETCH_MODE = $save;
 371          }
 372          return $indexes;
 373      }
 374      
 375  	function BeginTrans()
 376      {    
 377          if ($this->transOff) return true;
 378          $this->transCnt += 1;
 379          $this->autoCommit = false;
 380          $this->_commit = OCI_DEFAULT;
 381          return true;
 382      }
 383      
 384  	function CommitTrans($ok=true) 
 385      { 
 386          if ($this->transOff) return true;
 387          if (!$ok) return $this->RollbackTrans();
 388          
 389          if ($this->transCnt) $this->transCnt -= 1;
 390          $ret = OCIcommit($this->_connectionID);
 391          $this->_commit = OCI_COMMIT_ON_SUCCESS;
 392          $this->autoCommit = true;
 393          return $ret;
 394      }
 395      
 396  	function RollbackTrans()
 397      {
 398          if ($this->transOff) return true;
 399          if ($this->transCnt) $this->transCnt -= 1;
 400          $ret = OCIrollback($this->_connectionID);
 401          $this->_commit = OCI_COMMIT_ON_SUCCESS;
 402          $this->autoCommit = true;
 403          return $ret;
 404      }
 405      
 406      
 407  	function SelectDB($dbName) 
 408      {
 409          return false;
 410      }
 411  
 412  	function ErrorMsg() 
 413      {
 414          if ($this->_errorMsg !== false) return $this->_errorMsg;
 415  
 416          if (is_resource($this->_stmt)) $arr = @OCIerror($this->_stmt);
 417          if (empty($arr)) {
 418              $arr = @OCIerror($this->_connectionID);
 419              if ($arr === false) $arr = @OCIError();
 420              if ($arr === false) return '';
 421          }
 422          $this->_errorMsg = $arr['message'];
 423          $this->_errorCode = $arr['code'];
 424          return $this->_errorMsg;
 425      }
 426  
 427  	function ErrorNo() 
 428      {
 429          if ($this->_errorCode !== false) return $this->_errorCode;
 430          
 431          if (is_resource($this->_stmt)) $arr = @OCIError($this->_stmt);
 432          if (empty($arr)) {
 433              $arr = @OCIError($this->_connectionID);
 434              if ($arr == false) $arr = @OCIError();
 435              if ($arr == false) return '';
 436          }
 437          
 438          $this->_errorMsg = $arr['message'];
 439          $this->_errorCode = $arr['code'];
 440          
 441          return $arr['code'];
 442      }
 443      
 444      // Format date column in sql string given an input format that understands Y M D

 445  	function SQLDate($fmt, $col=false)
 446      {    
 447          if (!$col) $col = $this->sysTimeStamp;
 448          $s = 'TO_CHAR('.$col.",'";
 449          
 450          $len = strlen($fmt);
 451          for ($i=0; $i < $len; $i++) {
 452              $ch = $fmt[$i];
 453              switch($ch) {
 454              case 'Y':
 455              case 'y':
 456                  $s .= 'YYYY';
 457                  break;
 458              case 'Q':
 459              case 'q':
 460                  $s .= 'Q';
 461                  break;
 462                  
 463              case 'M':
 464                  $s .= 'Mon';
 465                  break;
 466                  
 467              case 'm':
 468                  $s .= 'MM';
 469                  break;
 470              case 'D':
 471              case 'd':
 472                  $s .= 'DD';
 473                  break;
 474              
 475              case 'H':
 476                  $s.= 'HH24';
 477                  break;
 478                  
 479              case 'h':
 480                  $s .= 'HH';
 481                  break;
 482                  
 483              case 'i':
 484                  $s .= 'MI';
 485                  break;
 486              
 487              case 's':
 488                  $s .= 'SS';
 489                  break;
 490              
 491              case 'a':
 492              case 'A':
 493                  $s .= 'AM';
 494                  break;
 495                  
 496              default:
 497              // handle escape characters...

 498                  if ($ch == '\\') {
 499                      $i++;
 500                      $ch = substr($fmt,$i,1);
 501                  }
 502                  if (strpos('-/.:;, ',$ch) !== false) $s .= $ch;
 503                  else $s .= '"'.$ch.'"';
 504                  
 505              }
 506          }
 507          return $s. "')";
 508      }
 509      
 510      
 511      /*

 512      This algorithm makes use of

 513      

 514      a. FIRST_ROWS hint

 515      The FIRST_ROWS hint explicitly chooses the approach to optimize response time, 

 516      that is, minimum resource usage to return the first row. Results will be returned 

 517      as soon as they are identified. 

 518  

 519      b. Uses rownum tricks to obtain only the required rows from a given offset.

 520       As this uses complicated sql statements, we only use this if the $offset >= 100. 

 521       This idea by Tomas V V Cox.

 522       

 523       This implementation does not appear to work with oracle 8.0.5 or earlier. Comment

 524       out this function then, and the slower SelectLimit() in the base class will be used.

 525      */
 526      function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
 527      {
 528          // seems that oracle only supports 1 hint comment in 8i

 529          if ($this->firstrows) {
 530              if (strpos($sql,'/*+') !== false)

 531                  $sql = str_replace('/*+ ','/*+FIRST_ROWS ',$sql);

 532              else

 533                  $sql = preg_replace('/^[ \t\n]*select/i','SELECT /*+FIRST_ROWS*/',$sql);
 534          }
 535          
 536          if ($offset < $this->selectOffsetAlg1) {
 537              if ($nrows > 0) {    
 538                  if ($offset > 0) $nrows += $offset;
 539                  //$inputarr['adodb_rownum'] = $nrows;

 540                  if ($this->databaseType == 'oci8po') {
 541                      $sql = "select * from (".$sql.") where rownum <= ?";
 542                  } else {
 543                      $sql = "select * from (".$sql.") where rownum <= :adodb_offset";
 544                  } 
 545                  $inputarr['adodb_offset'] = $nrows;
 546                  $nrows = -1;
 547              }
 548              // note that $nrows = 0 still has to work ==> no rows returned

 549  
 550              $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
 551              return $rs;
 552              
 553          } else {
 554               // Algorithm by Tomas V V Cox, from PEAR DB oci8.php

 555              
 556               // Let Oracle return the name of the columns

 557              $q_fields = "SELECT * FROM (".$sql.") WHERE NULL = NULL";
 558               
 559              $false = false;
 560              if (! $stmt_arr = $this->Prepare($q_fields)) {
 561                  return $false;
 562              }
 563              $stmt = $stmt_arr[1];
 564               
 565               if (is_array($inputarr)) {
 566                   foreach($inputarr as $k => $v) {
 567                      if (is_array($v)) {
 568                          if (sizeof($v) == 2) // suggested by g.giunta@libero.
 569                              OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]);
 570                          else
 571                              OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]);
 572                      } else {
 573                          $len = -1;
 574                          if ($v === ' ') $len = 1;
 575                          if (isset($bindarr)) {    // is prepared sql, so no need to ocibindbyname again
 576                              $bindarr[$k] = $v;
 577                          } else {                 // dynamic sql, so rebind every time
 578                              OCIBindByName($stmt,":$k",$inputarr[$k],$len);
 579                          }
 580                      }
 581                  }
 582              }
 583              
 584               if (!OCIExecute($stmt, OCI_DEFAULT)) {
 585                   OCIFreeStatement($stmt); 
 586                   return $false;
 587               }
 588               
 589               $ncols = OCINumCols($stmt);
 590               for ( $i = 1; $i <= $ncols; $i++ ) {
 591                   $cols[] = '"'.OCIColumnName($stmt, $i).'"';
 592               }
 593               $result = false;
 594              
 595               OCIFreeStatement($stmt); 
 596               $fields = implode(',', $cols);
 597               $nrows += $offset;
 598               $offset += 1; // in Oracle rownum starts at 1

 599              
 600              if ($this->databaseType == 'oci8po') {
 601                       $sql = "SELECT $fields FROM".
 602                        "(SELECT rownum as adodb_rownum, $fields FROM".
 603                        " ($sql) WHERE rownum <= ?".
 604                        ") WHERE adodb_rownum >= ?";
 605                  } else {
 606                       $sql = "SELECT $fields FROM".
 607                        "(SELECT rownum as adodb_rownum, $fields FROM".
 608                        " ($sql) WHERE rownum <= :adodb_nrows".
 609                        ") WHERE adodb_rownum >= :adodb_offset";
 610                  } 
 611                  $inputarr['adodb_nrows'] = $nrows;
 612                  $inputarr['adodb_offset'] = $offset;
 613                  
 614              if ($secs2cache>0) $rs =& $this->CacheExecute($secs2cache, $sql,$inputarr);
 615              else $rs =& $this->Execute($sql,$inputarr);
 616              return $rs;
 617          }
 618      
 619      }
 620      
 621      /**

 622      * Usage:

 623      * Store BLOBs and CLOBs

 624      *

 625      * Example: to store $var in a blob

 626      *

 627      *    $conn->Execute('insert into TABLE (id,ablob) values(12,empty_blob())');

 628      *    $conn->UpdateBlob('TABLE', 'ablob', $varHoldingBlob, 'ID=12', 'BLOB');

 629      *    

 630      *    $blobtype supports 'BLOB' and 'CLOB', but you need to change to 'empty_clob()'.

 631      *

 632      *  to get length of LOB:

 633      *      select DBMS_LOB.GETLENGTH(ablob) from TABLE

 634      *

 635      * If you are using CURSOR_SHARING = force, it appears this will case a segfault

 636      * under oracle 8.1.7.0. Run:

 637      *     $db->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT');

 638      * before UpdateBlob() then...

 639      */
 640  
 641  	function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
 642      {
 643          
 644          //if (strlen($val) < 4000) return $this->Execute("UPDATE $table SET $column=:blob WHERE $where",array('blob'=>$val)) != false;

 645          
 646          switch(strtoupper($blobtype)) {
 647          default: ADOConnection::outp("<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
 648          case 'BLOB': $type = OCI_B_BLOB; break;
 649          case 'CLOB': $type = OCI_B_CLOB; break;
 650          }
 651          
 652          if ($this->databaseType == 'oci8po') 
 653              $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
 654          else 
 655              $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
 656          
 657          $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB);
 658          $arr['blob'] = array($desc,-1,$type);
 659          if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT');
 660          $commit = $this->autoCommit;
 661          if ($commit) $this->BeginTrans();
 662          $rs = $this->Execute($sql,$arr);
 663          if ($rez = !empty($rs)) $desc->save($val);
 664          $desc->free();
 665          if ($commit) $this->CommitTrans();
 666          if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=FORCE');
 667          
 668          if ($rez) $rs->Close();
 669          return $rez;
 670      }
 671      
 672      /**

 673      * Usage:  store file pointed to by $var in a blob

 674      */
 675  	function UpdateBlobFile($table,$column,$val,$where,$blobtype='BLOB')
 676      {
 677          switch(strtoupper($blobtype)) {
 678          default: ADOConnection::outp( "<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
 679          case 'BLOB': $type = OCI_B_BLOB; break;
 680          case 'CLOB': $type = OCI_B_CLOB; break;
 681          }
 682          
 683          if ($this->databaseType == 'oci8po') 
 684              $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
 685          else 
 686              $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
 687          
 688          $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB);
 689          $arr['blob'] = array($desc,-1,$type);
 690          
 691          $this->BeginTrans();
 692          $rs = ADODB_oci8::Execute($sql,$arr);
 693          if ($rez = !empty($rs)) $desc->savefile($val);
 694          $desc->free();
 695          $this->CommitTrans();
 696          
 697          if ($rez) $rs->Close();
 698          return $rez;
 699      }
 700  
 701      
 702      /*

 703          Example of usage:

 704          

 705          $stmt = $this->Prepare('insert into emp (empno, ename) values (:empno, :ename)');

 706      */
 707  	function Prepare($sql,$cursor=false)
 708      {
 709      static $BINDNUM = 0;
 710      
 711          $stmt = OCIParse($this->_connectionID,$sql);
 712  
 713          if (!$stmt) return false;
 714  
 715          $BINDNUM += 1;
 716          
 717          $sttype = @OCIStatementType($stmt);
 718          if ($sttype == 'BEGIN' || $sttype == 'DECLARE') {
 719              return array($sql,$stmt,0,$BINDNUM, ($cursor) ? OCINewCursor($this->_connectionID) : false);
 720          }
 721          return array($sql,$stmt,0,$BINDNUM);
 722      }
 723      
 724      /*

 725          Call an oracle stored procedure and returns a cursor variable as a recordset. 

 726          Concept by Robert Tuttle robert@ud.com

 727          

 728          Example:

 729              Note: we return a cursor variable in :RS2

 730              $rs = $db->ExecuteCursor("BEGIN adodb.open_tab(:RS2); END;",'RS2');

 731              

 732              $rs = $db->ExecuteCursor(

 733                  "BEGIN :RS2 = adodb.getdata(:VAR1); END;", 

 734                  'RS2',

 735                  array('VAR1' => 'Mr Bean'));

 736              

 737      */
 738      function &ExecuteCursor($sql,$cursorName='rs',$params=false)
 739      {
 740          if (is_array($sql)) $stmt = $sql;
 741          else $stmt = ADODB_oci8::Prepare($sql,true); # true to allocate OCINewCursor

 742      
 743          if (is_array($stmt) && sizeof($stmt) >= 5) {
 744              $hasref = true;
 745              $this->Parameter($stmt, $ignoreCur, $cursorName, false, -1, OCI_B_CURSOR);
 746              if ($params) {
 747                  foreach($params as $k => $v) {
 748                      $this->Parameter($stmt,$params[$k], $k);
 749                  }
 750              }
 751          } else
 752              $hasref = false;
 753              
 754          $rs =& $this->Execute($stmt);
 755          if ($rs->databaseType == 'array') OCIFreeCursor($stmt[4]);
 756          else if ($hasref) $rs->_refcursor = $stmt[4];
 757          return $rs;
 758      }
 759      
 760      /*

 761          Bind a variable -- very, very fast for executing repeated statements in oracle. 

 762          Better than using

 763              for ($i = 0; $i < $max; $i++) {    

 764                  $p1 = ?; $p2 = ?; $p3 = ?;

 765                  $this->Execute("insert into table (col0, col1, col2) values (:0, :1, :2)", 

 766                      array($p1,$p2,$p3));

 767              }

 768          

 769          Usage:

 770              $stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)");

 771              $DB->Bind($stmt, $p1);

 772              $DB->Bind($stmt, $p2);

 773              $DB->Bind($stmt, $p3);

 774              for ($i = 0; $i < $max; $i++) {    

 775                  $p1 = ?; $p2 = ?; $p3 = ?;

 776                  $DB->Execute($stmt);

 777              }

 778              

 779          Some timings:        

 780              ** Test table has 3 cols, and 1 index. Test to insert 1000 records

 781              Time 0.6081s (1644.60 inserts/sec) with direct OCIParse/OCIExecute

 782              Time 0.6341s (1577.16 inserts/sec) with ADOdb Prepare/Bind/Execute

 783              Time 1.5533s ( 643.77 inserts/sec) with pure SQL using Execute

 784              

 785          Now if PHP only had batch/bulk updating like Java or PL/SQL...

 786      

 787          Note that the order of parameters differs from OCIBindByName,

 788          because we default the names to :0, :1, :2

 789      */
 790  	function Bind(&$stmt,&$var,$size=4000,$type=false,$name=false,$isOutput=false)
 791      {
 792          
 793          if (!is_array($stmt)) return false;
 794          
 795          if (($type == OCI_B_CURSOR) && sizeof($stmt) >= 5) { 
 796              return OCIBindByName($stmt[1],":".$name,$stmt[4],$size,$type);
 797          }
 798          
 799          if ($name == false) {
 800              if ($type !== false) $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size,$type);
 801              else $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size); // +1 byte for null terminator

 802              $stmt[2] += 1;
 803          } else if (oci_lob_desc($type)) {
 804              if ($this->debug) {
 805                  ADOConnection::outp("<b>Bind</b>: name = $name");
 806              }
 807              //we have to create a new Descriptor here

 808              $numlob = count($this->_refLOBs);
 809              $this->_refLOBs[$numlob]['LOB'] = OCINewDescriptor($this->_connectionID, oci_lob_desc($type));
 810              $this->_refLOBs[$numlob]['TYPE'] = $isOutput;
 811              
 812              $tmp = &$this->_refLOBs[$numlob]['LOB'];
 813              $rez = OCIBindByName($stmt[1], ":".$name, $tmp, -1, $type);
 814              if ($this->debug) {
 815                  ADOConnection::outp("<b>Bind</b>: descriptor has been allocated, var (".$name.") binded");
 816              }
 817              
 818              // if type is input then write data to lob now

 819              if ($isOutput == false) {
 820                  $var = $this->BlobEncode($var);
 821                  $tmp->WriteTemporary($var);
 822                  $this->_refLOBs[$numlob]['VAR'] = &$var;
 823                  if ($this->debug) {
 824                      ADOConnection::outp("<b>Bind</b>: LOB has been written to temp");
 825                  }
 826              } else {
 827                  $this->_refLOBs[$numlob]['VAR'] = &$var;
 828              }
 829              $rez = $tmp;
 830          } else {
 831              if ($this->debug) 
 832                  ADOConnection::outp("<b>Bind</b>: name = $name");
 833              
 834              if ($type !== false) $rez = OCIBindByName($stmt[1],":".$name,$var,$size,$type);
 835              else $rez = OCIBindByName($stmt[1],":".$name,$var,$size); // +1 byte for null terminator

 836          }
 837          
 838          return $rez;
 839      }
 840      
 841  	function Param($name,$type=false)
 842      {
 843          return ':'.$name;
 844      }
 845      
 846      /* 

 847      Usage:

 848          $stmt = $db->Prepare('select * from table where id =:myid and group=:group');

 849          $db->Parameter($stmt,$id,'myid');

 850          $db->Parameter($stmt,$group,'group');

 851          $db->Execute($stmt);

 852          

 853          @param $stmt Statement returned by Prepare() or PrepareSP().

 854          @param $var PHP variable to bind to

 855          @param $name Name of stored procedure variable name to bind to.

 856          @param [$isOutput] Indicates direction of parameter 0/false=IN  1=OUT  2= IN/OUT. This is ignored in oci8.

 857          @param [$maxLen] Holds an maximum length of the variable.

 858          @param [$type] The data type of $var. Legal values depend on driver.

 859          

 860          See OCIBindByName documentation at php.net.

 861      */
 862  	function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)
 863      {
 864              if  ($this->debug) {
 865                  $prefix = ($isOutput) ? 'Out' : 'In';
 866                  $ztype = (empty($type)) ? 'false' : $type;
 867                  ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
 868              }
 869              return $this->Bind($stmt,$var,$maxLen,$type,$name,$isOutput);
 870      }
 871      
 872      /*

 873      returns query ID if successful, otherwise false

 874      this version supports:

 875      

 876         1. $db->execute('select * from table');

 877         

 878         2. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)');

 879            $db->execute($prepared_statement, array(1,2,3));

 880            

 881         3. $db->execute('insert into table (a,b,c) values (:a,:b,:c)',array('a'=>1,'b'=>2,'c'=>3));

 882         

 883         4. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)');

 884            $db->bind($stmt,1); $db->bind($stmt,2); $db->bind($stmt,3); 

 885            $db->execute($stmt);

 886      */ 
 887  	function _query($sql,$inputarr)
 888      {
 889          
 890          if (is_array($sql)) { // is prepared sql
 891              $stmt = $sql[1];
 892              
 893              // we try to bind to permanent array, so that OCIBindByName is persistent

 894              // and carried out once only - note that max array element size is 4000 chars

 895              if (is_array($inputarr)) {
 896                  $bindpos = $sql[3];
 897                  if (isset($this->_bind[$bindpos])) {
 898                  // all tied up already

 899                      $bindarr = &$this->_bind[$bindpos];
 900                  } else {
 901                  // one statement to bind them all

 902                      $bindarr = array();
 903                      foreach($inputarr as $k => $v) {
 904                          $bindarr[$k] = $v;
 905                          OCIBindByName($stmt,":$k",$bindarr[$k],is_string($v) && strlen($v)>4000 ? -1 : 4000);
 906                      }
 907                      $this->_bind[$bindpos] = &$bindarr;
 908                  }
 909              }
 910          } else {
 911              $stmt=OCIParse($this->_connectionID,$sql);
 912          }
 913              
 914          $this->_stmt = $stmt;
 915          if (!$stmt) return false;
 916      
 917          if (defined('ADODB_PREFETCH_ROWS')) @OCISetPrefetch($stmt,ADODB_PREFETCH_ROWS);
 918              
 919          if (is_array($inputarr)) {
 920              foreach($inputarr as $k => $v) {
 921                  if (is_array($v)) {
 922                      if (sizeof($v) == 2) // suggested by g.giunta@libero.
 923                          OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]);
 924                      else
 925                          OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]);
 926                      
 927                      if ($this->debug==99) echo "name=:$k",' var='.$inputarr[$k][0],' len='.$v[1],' type='.$v[2],'<br>';
 928                  } else {
 929                      $len = -1;
 930                      if ($v === ' ') $len = 1;
 931                      if (isset($bindarr)) {    // is prepared sql, so no need to ocibindbyname again
 932                          $bindarr[$k] = $v;
 933                      } else {                 // dynamic sql, so rebind every time
 934                          OCIBindByName($stmt,":$k",$inputarr[$k],$len);
 935                      }
 936                  }
 937              }
 938          }
 939          
 940          $this->_errorMsg = false;
 941          $this->_errorCode = false;
 942          if (OCIExecute($stmt,$this->_commit)) {
 943  //OCIInternalDebug(1);            

 944              if (count($this -> _refLOBs) > 0) {
 945          
 946                  foreach ($this -> _refLOBs as $key => $value) {
 947                      if ($this -> _refLOBs[$key]['TYPE'] == true) {
 948                          $tmp = $this -> _refLOBs[$key]['LOB'] -> load();
 949                          if ($this -> debug) {
 950                              ADOConnection::outp("<b>OUT LOB</b>: LOB has been loaded. <br>");
 951                          }
 952                          //$_GLOBALS[$this -> _refLOBs[$key]['VAR']] = $tmp;

 953                          $this -> _refLOBs[$key]['VAR'] = $tmp;
 954                      } else {
 955                          $this->_refLOBs[$key]['LOB']->save($this->_refLOBs[$key]['VAR']);
 956                          $this -> _refLOBs[$key]['LOB']->free();
 957                          unset($this -> _refLOBs[$key]);
 958                          if ($this->debug) {
 959                              ADOConnection::outp("<b>IN LOB</b>: LOB has been saved. <br>");
 960                          }
 961                      }                    
 962                  }
 963              }
 964          
 965              switch (@OCIStatementType($stmt)) {
 966                  case "SELECT":
 967                      return $stmt;
 968                  
 969                  case 'DECLARE':
 970                  case "BEGIN":
 971                      if (is_array($sql) && !empty($sql[4])) {
 972                          $cursor = $sql[4];
 973                          if (is_resource($cursor)) {
 974                              $ok = OCIExecute($cursor);    
 975                              return $cursor;
 976                          }
 977                          return $stmt;
 978                      } else {
 979                          if (is_resource($stmt)) {
 980                              OCIFreeStatement($stmt);
 981                              return true;
 982                          }
 983                          return $stmt;
 984                      }
 985                      break;
 986                  default :
 987                      // ociclose -- no because it could be used in a LOB?

 988                      return true;
 989              }
 990          }
 991          return false;
 992      }
 993      
 994      // returns true or false

 995  	function _close()
 996      {
 997          if (!$this->_connectionID) return;
 998          
 999          if (!$this->autoCommit) OCIRollback($this->_connectionID);
1000          if (count($this->_refLOBs) > 0) {
1001              foreach ($this ->_refLOBs as $key => $value) {
1002                  $this->_refLOBs[$key]['LOB']->free();
1003                  unset($this->_refLOBs[$key]);
1004              }
1005          }
1006          OCILogoff($this->_connectionID);
1007          
1008          $this->_stmt = false;
1009          $this->_connectionID = false;
1010      }
1011      
1012  	function MetaPrimaryKeys($table, $owner=false,$internalKey=false)
1013      {
1014          if ($internalKey) return array('ROWID');
1015          
1016      // tested with oracle 8.1.7

1017          $table = strtoupper($table);
1018          if ($owner) {
1019              $owner_clause = "AND ((a.OWNER = b.OWNER) AND (a.OWNER = UPPER('$owner')))";
1020              $ptab = 'ALL_';
1021          } else {
1022              $owner_clause = '';
1023              $ptab = 'USER_';
1024          }
1025          $sql = "
1026  SELECT /*+ RULE */ distinct b.column_name
1027     FROM {$ptab}CONSTRAINTS a
1028        , {$ptab}CONS_COLUMNS b
1029    WHERE ( UPPER(b.table_name) = ('$table'))
1030      AND (UPPER(a.table_name) = ('$table') and a.constraint_type = 'P')
1031      $owner_clause
1032      AND (a.constraint_name = b.constraint_name)";
1033  
1034           $rs = $this->Execute($sql);
1035          if ($rs && !$rs->EOF) {
1036              $arr =& $rs->GetArray();
1037              $a = array();
1038              foreach($arr as $v) {
1039                  $a[] = reset($v);
1040              }
1041              return $a;
1042          }
1043          else return false;
1044      }
1045      
1046      // http://gis.mit.edu/classes/11.521/sqlnotes/referential_integrity.html

1047  	function MetaForeignKeys($table, $owner=false)
1048      {
1049      global $ADODB_FETCH_MODE;
1050      
1051          $save = $ADODB_FETCH_MODE;
1052          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
1053          $table = $this->qstr(strtoupper($table));
1054          if (!$owner) {
1055              $owner = $this->user;
1056              $tabp = 'user_';
1057          } else
1058              $tabp = 'all_';
1059              
1060          $owner = ' and owner='.$this->qstr(strtoupper($owner));
1061          
1062          $sql = 
1063  "select constraint_name,r_owner,r_constraint_name 
1064      from {$tabp}constraints
1065      where constraint_type = 'R' and table_name = $table $owner";
1066          
1067          $constraints =& $this->GetArray($sql);
1068          $arr = false;
1069          foreach($constraints as $constr) {
1070              $cons = $this->qstr($constr[0]);
1071              $rowner = $this->qstr($constr[1]);
1072              $rcons = $this->qstr($constr[2]);
1073              $cols = $this->GetArray("select column_name from {$tabp}cons_columns where constraint_name=$cons $owner order by position");
1074              $tabcol = $this->GetArray("select table_name,column_name from {$tabp}cons_columns where owner=$rowner and constraint_name=$rcons order by position");
1075              
1076              if ($cols && $tabcol) 
1077                  for ($i=0, $max=sizeof($cols); $i < $max; $i++) {
1078                      $arr[$tabcol[$i][0]] = $cols[$i][0].'='.$tabcol[$i][1];
1079                  }
1080          }
1081          $ADODB_FETCH_MODE = $save;
1082          
1083          return $arr;
1084      }
1085  
1086      
1087  	function CharMax()
1088      {
1089          return 4000;
1090      }
1091      
1092  	function TextMax()
1093      {
1094          return 4000;
1095      }
1096      
1097      /**

1098       * Quotes a string.

1099       * An example is  $db->qstr("Don't bother",magic_quotes_runtime());

1100       * 

1101       * @param s            the string to quote

1102       * @param [magic_quotes]    if $s is GET/POST var, set to get_magic_quotes_gpc().

1103       *                This undoes the stupidity of magic quotes for GPC.

1104       *

1105       * @return  quoted string to be sent back to database

1106       */
1107  	function qstr($s,$magic_quotes=false)
1108      {    
1109      $nofixquotes=false;
1110      
1111          if ($this->noNullStrings && strlen($s)==0)$s = ' ';
1112          if (!$magic_quotes) {    
1113              if ($this->replaceQuote[0] == '\\'){
1114                  $s = str_replace('\\','\\\\',$s);
1115              }
1116              return  "'".str_replace("'",$this->replaceQuote,$s)."'";
1117          }
1118          
1119          // undo magic quotes for "

1120          $s = str_replace('\\"','"',$s);
1121          
1122          $s = str_replace('\\\\','\\',$s);
1123          return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
1124          
1125      }
1126      
1127  }
1128  
1129  /*--------------------------------------------------------------------------------------

1130           Class Name: Recordset

1131  --------------------------------------------------------------------------------------*/
1132  
1133  class ADORecordset_oci8 extends ADORecordSet {
1134  
1135      var $databaseType = 'oci8';
1136      var $bind=false;
1137      var $_fieldobjs;
1138      
1139      //var $_arr = false;

1140          
1141  	function ADORecordset_oci8($queryID,$mode=false)
1142      {
1143          if ($mode === false) { 
1144              global $ADODB_FETCH_MODE;
1145              $mode = $ADODB_FETCH_MODE;
1146          }
1147          switch ($mode)
1148          {
1149          case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1150          case ADODB_FETCH_DEFAULT:
1151          case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1152          case ADODB_FETCH_NUM: 
1153          default:
1154          $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1155          }
1156          
1157          $this->adodbFetchMode = $mode;
1158          $this->_queryID = $queryID;
1159      }
1160  
1161  
1162  	function Init()
1163      {
1164          if ($this->_inited) return;
1165          
1166          $this->_inited = true;
1167          if ($this->_queryID) {
1168              
1169              $this->_currentRow = 0;
1170              @$this->_initrs();
1171              $this->EOF = !$this->_fetch();
1172              
1173              /*

1174              // based on idea by Gaetano Giunta to detect unusual oracle errors

1175              // see http://phplens.com/lens/lensforum/msgs.php?id=6771

1176              $err = OCIError($this->_queryID);

1177              if ($err && $this->connection->debug) ADOConnection::outp($err);

1178              */
1179              
1180              if (!is_array($this->fields)) {
1181                  $this->_numOfRows = 0;
1182                  $this->fields = array();
1183              }
1184          } else {
1185              $this->fields = array();
1186              $this->_numOfRows = 0;
1187              $this->_numOfFields = 0;
1188              $this->EOF = true;
1189          }
1190      }
1191      
1192  	function _initrs()
1193      {
1194          $this->_numOfRows = -1;
1195          $this->_numOfFields = OCInumcols($this->_queryID);
1196          if ($this->_numOfFields>0) {
1197              $this->_fieldobjs = array();
1198              $max = $this->_numOfFields;
1199              for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i);
1200          }
1201      }
1202  
1203        /*        Returns: an object containing field information.

1204                Get column information in the Recordset object. fetchField() can be used in order to obtain information about

1205                fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by

1206                fetchField() is retrieved.        */
1207  
1208      function &_FetchField($fieldOffset = -1)
1209      {
1210          $fld = new ADOFieldObject;
1211          $fieldOffset += 1;
1212          $fld->name =OCIcolumnname($this->_queryID, $fieldOffset);
1213          $fld->type = OCIcolumntype($this->_queryID, $fieldOffset);
1214          $fld->max_length = OCIcolumnsize($this->_queryID, $fieldOffset);
1215           if ($fld->type == 'NUMBER') {
1216               $p = OCIColumnPrecision($this->_queryID, $fieldOffset);
1217              $sc = OCIColumnScale($this->_queryID, $fieldOffset);
1218              if ($p != 0 && $sc == 0) $fld->type = 'INT';
1219              //echo " $this->name ($p.$sc) ";

1220           }
1221          return $fld;
1222      }
1223      
1224      /* For some reason, OCIcolumnname fails when called after _initrs() so we cache it */

1225      function &FetchField($fieldOffset = -1)
1226      {
1227          return $this->_fieldobjs[$fieldOffset];
1228      }
1229      
1230      
1231      /*

1232      // 10% speedup to move MoveNext to child class

1233      function _MoveNext() 

1234      {

1235      //global $ADODB_EXTENSION;if ($ADODB_EXTENSION) return @adodb_movenext($this);

1236          

1237          if ($this->EOF) return false;

1238          

1239          $this->_currentRow++;

1240          if(@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode))

1241              return true;

1242          $this->EOF = true;

1243          

1244          return false;

1245      }    */
1246      
1247      
1248  	function MoveNext()
1249      {
1250          if (@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) {
1251              $this->_currentRow += 1;
1252              return true;
1253          }
1254          if (!$this->EOF) {
1255              $this->_currentRow += 1;
1256              $this->EOF = true;
1257          }
1258          return false;
1259      }
1260      
1261      
1262      /* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */

1263      function &GetArrayLimit($nrows,$offset=-1) 
1264      {
1265          if ($offset <= 0) {
1266              $arr =& $this->GetArray($nrows);
1267              return $arr;
1268          }
1269          for ($i=1; $i < $offset; $i++) 
1270              if (!@OCIFetch($this->_queryID)) return array();
1271              
1272          if (!@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) return array();
1273          $results = array();
1274          $cnt = 0;
1275          while (!$this->EOF && $nrows != $cnt) {
1276              $results[$cnt++] = $this->fields;
1277              $this->MoveNext();
1278          }
1279          
1280          return $results;
1281      }
1282  
1283      
1284      /* Use associative array to get fields array */

1285  	function Fields($colname)
1286      {
1287          if (!$this->bind) {
1288              $this->bind = array();
1289              for ($i=0; $i < $this->_numOfFields; $i++) {
1290                  $o = $this->FetchField($i);
1291                  $this->bind[strtoupper($o->name)] = $i;
1292              }
1293          }
1294          
1295           return $this->fields[$this->bind[strtoupper($colname)]];
1296      }
1297      
1298  
1299  
1300  	function _seek($row)
1301      {
1302          return false;
1303      }
1304  
1305  	function _fetch() 
1306      {
1307          return @OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode);
1308      }
1309  
1310      /*        close() only needs to be called if you are worried about using too much memory while your script

1311              is running. All associated result memory for the specified result identifier will automatically be freed.        */
1312  
1313  	function _close() 
1314      {
1315          if ($this->connection->_stmt === $this->_queryID) $this->connection->_stmt = false;
1316          if (!empty($this->_refcursor)) {
1317              OCIFreeCursor($this->_refcursor);
1318              $this->_refcursor = false;
1319          }
1320          @OCIFreeStatement($this->_queryID);
1321           $this->_queryID = false;
1322          
1323      }
1324  
1325  	function MetaType($t,$len=-1)
1326      {
1327          if (is_object($t)) {
1328              $fieldobj = $t;
1329              $t = $fieldobj->type;
1330              $len = $fieldobj->max_length;
1331          }
1332          switch (strtoupper($t)) {
1333           case 'VARCHAR':
1334           case 'VARCHAR2':
1335          case 'CHAR':
1336          case 'VARBINARY':
1337          case 'BINARY':
1338          case 'NCHAR':
1339          case 'NVARCHAR':
1340          case 'NVARCHAR2':
1341                   if (isset($this) && $len <= $this->blobSize) return 'C';
1342          
1343          case 'NCLOB':
1344          case 'LONG':
1345          case 'LONG VARCHAR':
1346          case 'CLOB':
1347          return 'X';
1348          
1349          case 'LONG RAW':
1350          case 'LONG VARBINARY':
1351          case 'BLOB':
1352              return 'B';
1353          
1354          case 'DATE': 
1355              return  ($this->connection->datetime) ? 'T' : 'D';
1356          
1357          
1358          case 'TIMESTAMP': return 'T';
1359          
1360          case 'INT': 
1361          case 'SMALLINT':
1362          case 'INTEGER': 
1363              return 'I';
1364              
1365          default: return 'N';
1366          }
1367      }
1368  }
1369  
1370  class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 {    
1371  	function ADORecordSet_ext_oci8($queryID,$mode=false) 
1372      {
1373          if ($mode === false) { 
1374              global $ADODB_FETCH_MODE;
1375              $mode = $ADODB_FETCH_MODE;
1376          }
1377          switch ($mode)
1378          {
1379          case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1380          case ADODB_FETCH_DEFAULT:
1381          case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1382          case ADODB_FETCH_NUM: 
1383          default: $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1384          }
1385          $this->adodbFetchMode = $mode;
1386          $this->_queryID = $queryID;
1387      }
1388      
1389  	function MoveNext()
1390      {
1391          return adodb_movenext($this);
1392      }
1393  }
1394  ?>

title

Description

title

Description

title

Description

title

title

Body