[ Index ]
 

Code source de vtiger CRM 5.0.2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/adodb/drivers/ -> adodb-oci8.inc.php (source)

   1  <?php
   2  /*
   3  
   4    version V4.90 8 June 2006 (c) 2000-2006 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 (2000–2049), and years over 50 as years in
  34  the 20th century (1950–1999). 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          if (empty($retarr))
 135              return  $false;
 136          else 
 137              return $retarr;
 138      }
 139      
 140  	function Time()
 141      {
 142          $rs =& $this->Execute("select TO_CHAR($this->sysTimeStamp,'YYYY-MM-DD HH24:MI:SS') from dual");
 143          if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields));
 144          
 145          return false;
 146      }
 147   
 148  /*
 149  
 150    Multiple modes of connection are supported:
 151    
 152    a. Local Database
 153      $conn->Connect(false,'scott','tiger');
 154    
 155    b. From tnsnames.ora
 156      $conn->Connect(false,'scott','tiger',$tnsname); 
 157      $conn->Connect($tnsname,'scott','tiger'); 
 158    
 159    c. Server + service name
 160      $conn->Connect($serveraddress,'scott,'tiger',$service_name);
 161    
 162    d. Server + SID
 163        $conn->connectSID = true;
 164      $conn->Connect($serveraddress,'scott,'tiger',$SID);
 165  
 166  
 167  Example TNSName:
 168  ---------------
 169  NATSOFT.DOMAIN =
 170    (DESCRIPTION =
 171      (ADDRESS_LIST =
 172        (ADDRESS = (PROTOCOL = TCP)(HOST = kermit)(PORT = 1523))
 173      )
 174      (CONNECT_DATA =
 175        (SERVICE_NAME = natsoft.domain)
 176      )
 177    )
 178    
 179    There are 3 connection modes, 0 = non-persistent, 1 = persistent, 2 = force new connection
 180      
 181  */
 182  	function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$mode=0)
 183      {
 184          if (!function_exists('OCIPLogon')) return null;
 185          
 186          
 187          $this->_errorMsg = false;
 188          $this->_errorCode = false;
 189          
 190          if($argHostname) { // added by Jorma Tuomainen <jorma.tuomainen@ppoy.fi>
 191              if (empty($argDatabasename)) $argDatabasename = $argHostname;
 192              else {
 193                  if(strpos($argHostname,":")) {
 194                      $argHostinfo=explode(":",$argHostname);
 195                         $argHostname=$argHostinfo[0];
 196                      $argHostport=$argHostinfo[1];
 197                   } else {
 198                      $argHostport = empty($this->port)?  "1521" : $this->port;
 199                     }
 200                  
 201                  if ($this->connectSID) {
 202                      $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
 203                      .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))";
 204                  } else
 205                      $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
 206                      .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))";
 207              }
 208          }
 209                  
 210           //if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>";
 211          if ($mode==1) {
 212              $this->_connectionID = ($this->charSet) ? 
 213                  OCIPLogon($argUsername,$argPassword, $argDatabasename)
 214                  :
 215                  OCIPLogon($argUsername,$argPassword, $argDatabasename, $this->charSet)
 216                  ;
 217              if ($this->_connectionID && $this->autoRollback)  OCIrollback($this->_connectionID);
 218          } else if ($mode==2) {
 219              $this->_connectionID = ($this->charSet) ? 
 220                  OCINLogon($argUsername,$argPassword, $argDatabasename)
 221                  :
 222                  OCINLogon($argUsername,$argPassword, $argDatabasename, $this->charSet);
 223                  
 224          } else {
 225              $this->_connectionID = ($this->charSet) ? 
 226                  OCILogon($argUsername,$argPassword, $argDatabasename)
 227                  :
 228                  OCILogon($argUsername,$argPassword, $argDatabasename,$this->charSet);
 229          }
 230          if (!$this->_connectionID) return false;
 231          if ($this->_initdate) {
 232              $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='".$this->NLS_DATE_FORMAT."'");
 233          }
 234          
 235          // looks like: 
 236          // Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production
 237          // $vers = OCIServerVersion($this->_connectionID);
 238          // if (strpos($vers,'8i') !== false) $this->ansiOuter = true;
 239          return true;
 240         }
 241      
 242  	function ServerInfo()
 243      {
 244          $arr['compat'] = $this->GetOne('select value from sys.database_compatible_level');
 245          $arr['description'] = @OCIServerVersion($this->_connectionID);
 246          $arr['version'] = ADOConnection::_findvers($arr['description']);
 247          return $arr;
 248      }
 249          // returns true or false
 250  	function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
 251      {
 252          return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,1);
 253      }
 254      
 255      // returns true or false
 256  	function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
 257      {
 258          return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,2);
 259      }
 260      
 261  	function _affectedrows()
 262      {
 263          if (is_resource($this->_stmt)) return @OCIRowCount($this->_stmt);
 264          return 0;
 265      }
 266      
 267  	function IfNull( $field, $ifNull ) 
 268      {
 269          return " NVL($field, $ifNull) "; // if Oracle
 270      }
 271      
 272      // format and return date string in database date format
 273  	function DBDate($d)
 274      {
 275          if (empty($d) && $d !== 0) return 'null';
 276          
 277          if (is_string($d)) $d = ADORecordSet::UnixDate($d);
 278          return "TO_DATE(".adodb_date($this->fmtDate,$d).",'".$this->NLS_DATE_FORMAT."')";
 279      }
 280  
 281  	function BindDate($d)
 282      {
 283          $d = ADOConnection::DBDate($d);
 284          if (strncmp($d,"'",1)) return $d;
 285          
 286          return substr($d,1,strlen($d)-2);
 287      }
 288      
 289  	function BindTimeStamp($d)
 290      {
 291          $d = ADOConnection::DBTimeStamp($d);
 292          if (strncmp($d,"'",1)) return $d;
 293          
 294          return substr($d,1,strlen($d)-2);
 295      }
 296      
 297      // format and return date string in database timestamp format
 298  	function DBTimeStamp($ts)
 299      {
 300          if (empty($ts) && $ts !== 0) return 'null';
 301          if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
 302          return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'RRRR-MM-DD, HH:MI:SS AM')";
 303      }
 304      
 305  	function RowLock($tables,$where,$flds='1 as ignore') 
 306      {
 307          if ($this->autoCommit) $this->BeginTrans();
 308          return $this->GetOne("select $flds from $tables where $where for update");
 309      }
 310      
 311      function &MetaTables($ttype=false,$showSchema=false,$mask=false) 
 312      {
 313          if ($mask) {
 314              $save = $this->metaTablesSQL;
 315              $mask = $this->qstr(strtoupper($mask));
 316              $this->metaTablesSQL .= " AND upper(table_name) like $mask";
 317          }
 318          $ret =& ADOConnection::MetaTables($ttype,$showSchema);
 319          
 320          if ($mask) {
 321              $this->metaTablesSQL = $save;
 322          }
 323          return $ret;
 324      }
 325      
 326      // Mark Newnham 
 327      function &MetaIndexes ($table, $primary = FALSE, $owner=false)
 328      {
 329          // save old fetch mode
 330          global $ADODB_FETCH_MODE;
 331  
 332          $save = $ADODB_FETCH_MODE;
 333          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 334  
 335          if ($this->fetchMode !== FALSE) {
 336                 $savem = $this->SetFetchMode(FALSE);
 337          }
 338  
 339          // get index details
 340          $table = strtoupper($table);
 341  
 342          // get Primary index
 343          $primary_key = '';
 344  
 345          $false = false;
 346          $rs = $this->Execute(sprintf("SELECT * FROM ALL_CONSTRAINTS WHERE UPPER(TABLE_NAME)='%s' AND CONSTRAINT_TYPE='P'",$table));
 347          if ($row = $rs->FetchRow())
 348             $primary_key = $row[1]; //constraint_name
 349  
 350          if ($primary==TRUE && $primary_key=='') {
 351               if (isset($savem)) 
 352                  $this->SetFetchMode($savem);
 353              $ADODB_FETCH_MODE = $save;
 354              return $false; //There is no primary key
 355          }
 356  
 357          $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));
 358  
 359          
 360          if (!is_object($rs)) {
 361              if (isset($savem)) 
 362                  $this->SetFetchMode($savem);
 363              $ADODB_FETCH_MODE = $save;
 364              return $false;
 365          }
 366  
 367          $indexes = array ();
 368          // parse index data into array
 369  
 370          while ($row = $rs->FetchRow()) {
 371              if ($primary && $row[0] != $primary_key) continue;
 372              if (!isset($indexes[$row[0]])) {
 373                  $indexes[$row[0]] = array(
 374                     'unique' => ($row[1] == 'UNIQUE'),
 375                     'columns' => array()
 376                  );
 377              }
 378              $indexes[$row[0]]['columns'][$row[2] - 1] = $row[3];
 379          }
 380  
 381          // sort columns by order in the index
 382          foreach ( array_keys ($indexes) as $index ) {
 383              ksort ($indexes[$index]['columns']);
 384          }
 385  
 386          if (isset($savem)) { 
 387              $this->SetFetchMode($savem);
 388              $ADODB_FETCH_MODE = $save;
 389          }
 390          return $indexes;
 391      }
 392      
 393  	function BeginTrans()
 394      {    
 395          if ($this->transOff) return true;
 396          $this->transCnt += 1;
 397          $this->autoCommit = false;
 398          $this->_commit = OCI_DEFAULT;
 399          
 400          if ($this->_transmode) $this->Execute("SET TRANSACTION ".$this->_transmode);
 401          return true;
 402      }
 403      
 404  	function CommitTrans($ok=true) 
 405      { 
 406          if ($this->transOff) return true;
 407          if (!$ok) return $this->RollbackTrans();
 408          
 409          if ($this->transCnt) $this->transCnt -= 1;
 410          $ret = OCIcommit($this->_connectionID);
 411          $this->_commit = OCI_COMMIT_ON_SUCCESS;
 412          $this->autoCommit = true;
 413          return $ret;
 414      }
 415      
 416  	function RollbackTrans()
 417      {
 418          if ($this->transOff) return true;
 419          if ($this->transCnt) $this->transCnt -= 1;
 420          $ret = OCIrollback($this->_connectionID);
 421          $this->_commit = OCI_COMMIT_ON_SUCCESS;
 422          $this->autoCommit = true;
 423          return $ret;
 424      }
 425      
 426      
 427  	function SelectDB($dbName) 
 428      {
 429          return false;
 430      }
 431  
 432  	function ErrorMsg() 
 433      {
 434          if ($this->_errorMsg !== false) return $this->_errorMsg;
 435  
 436          if (is_resource($this->_stmt)) $arr = @OCIerror($this->_stmt);
 437          if (empty($arr)) {
 438              $arr = @OCIerror($this->_connectionID);
 439              if ($arr === false) $arr = @OCIError();
 440              if ($arr === false) return '';
 441          }
 442          $this->_errorMsg = $arr['message'];
 443          $this->_errorCode = $arr['code'];
 444          return $this->_errorMsg;
 445      }
 446  
 447  	function ErrorNo() 
 448      {
 449          if ($this->_errorCode !== false) return $this->_errorCode;
 450          
 451          if (is_resource($this->_stmt)) $arr = @OCIError($this->_stmt);
 452          if (empty($arr)) {
 453              $arr = @OCIError($this->_connectionID);
 454              if ($arr == false) $arr = @OCIError();
 455              if ($arr == false) return '';
 456          }
 457          
 458          $this->_errorMsg = $arr['message'];
 459          $this->_errorCode = $arr['code'];
 460          
 461          return $arr['code'];
 462      }
 463      
 464      // Format date column in sql string given an input format that understands Y M D
 465  	function SQLDate($fmt, $col=false)
 466      {    
 467          if (!$col) $col = $this->sysTimeStamp;
 468          $s = 'TO_CHAR('.$col.",'";
 469          
 470          $len = strlen($fmt);
 471          for ($i=0; $i < $len; $i++) {
 472              $ch = $fmt[$i];
 473              switch($ch) {
 474              case 'Y':
 475              case 'y':
 476                  $s .= 'YYYY';
 477                  break;
 478              case 'Q':
 479              case 'q':
 480                  $s .= 'Q';
 481                  break;
 482                  
 483              case 'M':
 484                  $s .= 'Mon';
 485                  break;
 486                  
 487              case 'm':
 488                  $s .= 'MM';
 489                  break;
 490              case 'D':
 491              case 'd':
 492                  $s .= 'DD';
 493                  break;
 494              
 495              case 'H':
 496                  $s.= 'HH24';
 497                  break;
 498                  
 499              case 'h':
 500                  $s .= 'HH';
 501                  break;
 502                  
 503              case 'i':
 504                  $s .= 'MI';
 505                  break;
 506              
 507              case 's':
 508                  $s .= 'SS';
 509                  break;
 510              
 511              case 'a':
 512              case 'A':
 513                  $s .= 'AM';
 514                  break;
 515                  
 516              case 'w':
 517                  $s .= 'D';
 518                  break;
 519                  
 520              case 'l':
 521                  $s .= 'DAY';
 522                  break;
 523                  
 524               case 'W':
 525                  $s .= 'WW';
 526                  break;
 527                  
 528              default:
 529              // handle escape characters...
 530                  if ($ch == '\\') {
 531                      $i++;
 532                      $ch = substr($fmt,$i,1);
 533                  }
 534                  if (strpos('-/.:;, ',$ch) !== false) $s .= $ch;
 535                  else $s .= '"'.$ch.'"';
 536                  
 537              }
 538          }
 539          return $s. "')";
 540      }
 541      
 542      
 543      /*
 544      This algorithm makes use of
 545      
 546      a. FIRST_ROWS hint
 547      The FIRST_ROWS hint explicitly chooses the approach to optimize response time, 
 548      that is, minimum resource usage to return the first row. Results will be returned 
 549      as soon as they are identified. 
 550  
 551      b. Uses rownum tricks to obtain only the required rows from a given offset.
 552       As this uses complicated sql statements, we only use this if the $offset >= 100. 
 553       This idea by Tomas V V Cox.
 554       
 555       This implementation does not appear to work with oracle 8.0.5 or earlier. Comment
 556       out this function then, and the slower SelectLimit() in the base class will be used.
 557      */
 558      function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
 559      {
 560          // seems that oracle only supports 1 hint comment in 8i
 561          if ($this->firstrows) {
 562              if (strpos($sql,'/*+') !== false)
 563                  $sql = str_replace('/*+ ','/*+FIRST_ROWS ',$sql);
 564              else
 565                  $sql = preg_replace('/^[ \t\n]*select/i','SELECT /*+FIRST_ROWS*/',$sql);
 566          }
 567          
 568          if ($offset < $this->selectOffsetAlg1) {
 569              if ($nrows > 0) {    
 570                  if ($offset > 0) $nrows += $offset;
 571                  //$inputarr['adodb_rownum'] = $nrows;
 572                  if ($this->databaseType == 'oci8po') {
 573                      $sql = "select * from (".$sql.") where rownum <= ?";
 574                  } else {
 575                      $sql = "select * from (".$sql.") where rownum <= :adodb_offset";
 576                  } 
 577                  $inputarr['adodb_offset'] = $nrows;
 578                  $nrows = -1;
 579              }
 580              // note that $nrows = 0 still has to work ==> no rows returned
 581  
 582              $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
 583              return $rs;
 584              
 585          } else {
 586               // Algorithm by Tomas V V Cox, from PEAR DB oci8.php
 587              
 588               // Let Oracle return the name of the columns
 589              $q_fields = "SELECT * FROM (".$sql.") WHERE NULL = NULL";
 590               
 591              $false = false;
 592              if (! $stmt_arr = $this->Prepare($q_fields)) {
 593                  return $false;
 594              }
 595              $stmt = $stmt_arr[1];
 596               
 597               if (is_array($inputarr)) {
 598                   foreach($inputarr as $k => $v) {
 599                      if (is_array($v)) {
 600                          if (sizeof($v) == 2) // suggested by g.giunta@libero.
 601                              OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]);
 602                          else
 603                              OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]);
 604                      } else {
 605                          $len = -1;
 606                          if ($v === ' ') $len = 1;
 607                          if (isset($bindarr)) {    // is prepared sql, so no need to ocibindbyname again
 608                              $bindarr[$k] = $v;
 609                          } else {                 // dynamic sql, so rebind every time
 610                              OCIBindByName($stmt,":$k",$inputarr[$k],$len);
 611                          }
 612                      }
 613                  }
 614              }
 615              
 616               if (!OCIExecute($stmt, OCI_DEFAULT)) {
 617                   OCIFreeStatement($stmt); 
 618                   return $false;
 619               }
 620               
 621               $ncols = OCINumCols($stmt);
 622               for ( $i = 1; $i <= $ncols; $i++ ) {
 623                   $cols[] = '"'.OCIColumnName($stmt, $i).'"';
 624               }
 625               $result = false;
 626              
 627               OCIFreeStatement($stmt); 
 628               $fields = implode(',', $cols);
 629               $nrows += $offset;
 630               $offset += 1; // in Oracle rownum starts at 1
 631              
 632              if ($this->databaseType == 'oci8po') {
 633                       $sql = "SELECT $fields FROM".
 634                        "(SELECT rownum as adodb_rownum, $fields FROM".
 635                        " ($sql) WHERE rownum <= ?".
 636                        ") WHERE adodb_rownum >= ?";
 637                  } else {
 638                       $sql = "SELECT $fields FROM".
 639                        "(SELECT rownum as adodb_rownum, $fields FROM".
 640                        " ($sql) WHERE rownum <= :adodb_nrows".
 641                        ") WHERE adodb_rownum >= :adodb_offset";
 642                  } 
 643                  $inputarr['adodb_nrows'] = $nrows;
 644                  $inputarr['adodb_offset'] = $offset;
 645                  
 646              if ($secs2cache>0) $rs =& $this->CacheExecute($secs2cache, $sql,$inputarr);
 647              else $rs =& $this->Execute($sql,$inputarr);
 648              return $rs;
 649          }
 650      
 651      }
 652      
 653      /**
 654      * Usage:
 655      * Store BLOBs and CLOBs
 656      *
 657      * Example: to store $var in a blob
 658      *
 659      *    $conn->Execute('insert into TABLE (id,ablob) values(12,empty_blob())');
 660      *    $conn->UpdateBlob('TABLE', 'ablob', $varHoldingBlob, 'ID=12', 'BLOB');
 661      *    
 662      *    $blobtype supports 'BLOB' and 'CLOB', but you need to change to 'empty_clob()'.
 663      *
 664      *  to get length of LOB:
 665      *      select DBMS_LOB.GETLENGTH(ablob) from TABLE
 666      *
 667      * If you are using CURSOR_SHARING = force, it appears this will case a segfault
 668      * under oracle 8.1.7.0. Run:
 669      *     $db->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT');
 670      * before UpdateBlob() then...
 671      */
 672  
 673  	function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
 674      {
 675          
 676          //if (strlen($val) < 4000) return $this->Execute("UPDATE $table SET $column=:blob WHERE $where",array('blob'=>$val)) != false;
 677          
 678          switch(strtoupper($blobtype)) {
 679          default: ADOConnection::outp("<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
 680          case 'BLOB': $type = OCI_B_BLOB; break;
 681          case 'CLOB': $type = OCI_B_CLOB; break;
 682          }
 683          
 684          if ($this->databaseType == 'oci8po') 
 685              $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
 686          else 
 687              $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
 688          
 689          $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB);
 690          $arr['blob'] = array($desc,-1,$type);
 691          if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT');
 692          $commit = $this->autoCommit;
 693          if ($commit) $this->BeginTrans();
 694          $rs = $this->_Execute($sql,$arr);
 695          if ($rez = !empty($rs)) $desc->save($val);
 696          $desc->free();
 697          if ($commit) $this->CommitTrans();
 698          if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=FORCE');
 699          
 700          if ($rez) $rs->Close();
 701          return $rez;
 702      }
 703      
 704      /**
 705      * Usage:  store file pointed to by $var in a blob
 706      */
 707  	function UpdateBlobFile($table,$column,$val,$where,$blobtype='BLOB')
 708      {
 709          switch(strtoupper($blobtype)) {
 710          default: ADOConnection::outp( "<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
 711          case 'BLOB': $type = OCI_B_BLOB; break;
 712          case 'CLOB': $type = OCI_B_CLOB; break;
 713          }
 714          
 715          if ($this->databaseType == 'oci8po') 
 716              $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
 717          else 
 718              $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
 719          
 720          $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB);
 721          $arr['blob'] = array($desc,-1,$type);
 722          
 723          $this->BeginTrans();
 724          $rs = ADODB_oci8::Execute($sql,$arr);
 725          if ($rez = !empty($rs)) $desc->savefile($val);
 726          $desc->free();
 727          $this->CommitTrans();
 728          
 729          if ($rez) $rs->Close();
 730          return $rez;
 731      }
 732  
 733          /**
 734       * Execute SQL 
 735       *
 736       * @param sql        SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text)
 737       * @param [inputarr]    holds the input data to bind to. Null elements will be set to null.
 738       * @return         RecordSet or false
 739       */
 740      function &Execute($sql,$inputarr=false) 
 741      {
 742          if ($this->fnExecute) {
 743              $fn = $this->fnExecute;
 744              $ret =& $fn($this,$sql,$inputarr);
 745              if (isset($ret)) return $ret;
 746          }
 747          if ($inputarr) {
 748              #if (!is_array($inputarr)) $inputarr = array($inputarr);
 749              
 750              $element0 = reset($inputarr);
 751              
 752              # is_object check because oci8 descriptors can be passed in
 753              if (is_array($element0) && !is_object(reset($element0))) {
 754                  if (is_string($sql))
 755                      $stmt = $this->Prepare($sql);
 756                  else
 757                      $stmt = $sql;
 758                      
 759                  foreach($inputarr as $arr) {
 760                      $ret =& $this->_Execute($stmt,$arr);
 761                      if (!$ret) return $ret;
 762                  }
 763              } else {
 764                  $ret =& $this->_Execute($sql,$inputarr);
 765              }
 766              
 767          } else {
 768              $ret =& $this->_Execute($sql,false);
 769          }
 770  
 771          return $ret;
 772      }
 773      
 774      /*
 775          Example of usage:
 776          
 777          $stmt = $this->Prepare('insert into emp (empno, ename) values (:empno, :ename)');
 778      */
 779  	function Prepare($sql,$cursor=false)
 780      {
 781      static $BINDNUM = 0;
 782      
 783          $stmt = OCIParse($this->_connectionID,$sql);
 784  
 785          if (!$stmt) return false;
 786  
 787          $BINDNUM += 1;
 788          
 789          $sttype = @OCIStatementType($stmt);
 790          if ($sttype == 'BEGIN' || $sttype == 'DECLARE') {
 791              return array($sql,$stmt,0,$BINDNUM, ($cursor) ? OCINewCursor($this->_connectionID) : false);
 792          }
 793          return array($sql,$stmt,0,$BINDNUM);
 794      }
 795      
 796      /*
 797          Call an oracle stored procedure and returns a cursor variable as a recordset. 
 798          Concept by Robert Tuttle robert@ud.com
 799          
 800          Example:
 801              Note: we return a cursor variable in :RS2
 802              $rs = $db->ExecuteCursor("BEGIN adodb.open_tab(:RS2); END;",'RS2');
 803              
 804              $rs = $db->ExecuteCursor(
 805                  "BEGIN :RS2 = adodb.getdata(:VAR1); END;", 
 806                  'RS2',
 807                  array('VAR1' => 'Mr Bean'));
 808              
 809      */
 810      function &ExecuteCursor($sql,$cursorName='rs',$params=false)
 811      {
 812          if (is_array($sql)) $stmt = $sql;
 813          else $stmt = ADODB_oci8::Prepare($sql,true); # true to allocate OCINewCursor
 814      
 815          if (is_array($stmt) && sizeof($stmt) >= 5) {
 816              $hasref = true;
 817              $ignoreCur = false;
 818              $this->Parameter($stmt, $ignoreCur, $cursorName, false, -1, OCI_B_CURSOR);
 819              if ($params) {
 820                  foreach($params as $k => $v) {
 821                      $this->Parameter($stmt,$params[$k], $k);
 822                  }
 823              }
 824          } else
 825              $hasref = false;
 826              
 827          $rs =& $this->Execute($stmt);
 828          if ($rs) {
 829              if ($rs->databaseType == 'array') OCIFreeCursor($stmt[4]);
 830              else if ($hasref) $rs->_refcursor = $stmt[4];
 831          }
 832          return $rs;
 833      }
 834      
 835      /*
 836          Bind a variable -- very, very fast for executing repeated statements in oracle. 
 837          Better than using
 838              for ($i = 0; $i < $max; $i++) {    
 839                  $p1 = ?; $p2 = ?; $p3 = ?;
 840                  $this->Execute("insert into table (col0, col1, col2) values (:0, :1, :2)", 
 841                      array($p1,$p2,$p3));
 842              }
 843          
 844          Usage:
 845              $stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)");
 846              $DB->Bind($stmt, $p1);
 847              $DB->Bind($stmt, $p2);
 848              $DB->Bind($stmt, $p3);
 849              for ($i = 0; $i < $max; $i++) {    
 850                  $p1 = ?; $p2 = ?; $p3 = ?;
 851                  $DB->Execute($stmt);
 852              }
 853              
 854          Some timings:        
 855              ** Test table has 3 cols, and 1 index. Test to insert 1000 records
 856              Time 0.6081s (1644.60 inserts/sec) with direct OCIParse/OCIExecute
 857              Time 0.6341s (1577.16 inserts/sec) with ADOdb Prepare/Bind/Execute
 858              Time 1.5533s ( 643.77 inserts/sec) with pure SQL using Execute
 859              
 860          Now if PHP only had batch/bulk updating like Java or PL/SQL...
 861      
 862          Note that the order of parameters differs from OCIBindByName,
 863          because we default the names to :0, :1, :2
 864      */
 865  	function Bind(&$stmt,&$var,$size=4000,$type=false,$name=false,$isOutput=false)
 866      {
 867          
 868          if (!is_array($stmt)) return false;
 869          
 870          if (($type == OCI_B_CURSOR) && sizeof($stmt) >= 5) { 
 871              return OCIBindByName($stmt[1],":".$name,$stmt[4],$size,$type);
 872          }
 873          
 874          if ($name == false) {
 875              if ($type !== false) $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size,$type);
 876              else $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size); // +1 byte for null terminator
 877              $stmt[2] += 1;
 878          } else if (oci_lob_desc($type)) {
 879              if ($this->debug) {
 880                  ADOConnection::outp("<b>Bind</b>: name = $name");
 881              }
 882              //we have to create a new Descriptor here
 883              $numlob = count($this->_refLOBs);
 884              $this->_refLOBs[$numlob]['LOB'] = OCINewDescriptor($this->_connectionID, oci_lob_desc($type));
 885              $this->_refLOBs[$numlob]['TYPE'] = $isOutput;
 886              
 887              $tmp = &$this->_refLOBs[$numlob]['LOB'];
 888              $rez = OCIBindByName($stmt[1], ":".$name, $tmp, -1, $type);
 889              if ($this->debug) {
 890                  ADOConnection::outp("<b>Bind</b>: descriptor has been allocated, var (".$name.") binded");
 891              }
 892              
 893              // if type is input then write data to lob now
 894              if ($isOutput == false) {
 895                  $var = $this->BlobEncode($var);
 896                  $tmp->WriteTemporary($var);
 897                  $this->_refLOBs[$numlob]['VAR'] = &$var;
 898                  if ($this->debug) {
 899                      ADOConnection::outp("<b>Bind</b>: LOB has been written to temp");
 900                  }
 901              } else {
 902                  $this->_refLOBs[$numlob]['VAR'] = &$var;
 903              }
 904              $rez = $tmp;
 905          } else {
 906              if ($this->debug) 
 907                  ADOConnection::outp("<b>Bind</b>: name = $name");
 908              
 909              if ($type !== false) $rez = OCIBindByName($stmt[1],":".$name,$var,$size,$type);
 910              else $rez = OCIBindByName($stmt[1],":".$name,$var,$size); // +1 byte for null terminator
 911          }
 912          
 913          return $rez;
 914      }
 915      
 916  	function Param($name,$type=false)
 917      {
 918          return ':'.$name;
 919      }
 920      
 921      /* 
 922      Usage:
 923          $stmt = $db->Prepare('select * from table where id =:myid and group=:group');
 924          $db->Parameter($stmt,$id,'myid');
 925          $db->Parameter($stmt,$group,'group');
 926          $db->Execute($stmt);
 927          
 928          @param $stmt Statement returned by Prepare() or PrepareSP().
 929          @param $var PHP variable to bind to
 930          @param $name Name of stored procedure variable name to bind to.
 931          @param [$isOutput] Indicates direction of parameter 0/false=IN  1=OUT  2= IN/OUT. This is ignored in oci8.
 932          @param [$maxLen] Holds an maximum length of the variable.
 933          @param [$type] The data type of $var. Legal values depend on driver.
 934          
 935          See OCIBindByName documentation at php.net.
 936      */
 937  	function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)
 938      {
 939              if  ($this->debug) {
 940                  $prefix = ($isOutput) ? 'Out' : 'In';
 941                  $ztype = (empty($type)) ? 'false' : $type;
 942                  ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
 943              }
 944              return $this->Bind($stmt,$var,$maxLen,$type,$name,$isOutput);
 945      }
 946      
 947      /*
 948      returns query ID if successful, otherwise false
 949      this version supports:
 950      
 951         1. $db->execute('select * from table');
 952         
 953         2. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)');
 954            $db->execute($prepared_statement, array(1,2,3));
 955            
 956         3. $db->execute('insert into table (a,b,c) values (:a,:b,:c)',array('a'=>1,'b'=>2,'c'=>3));
 957         
 958         4. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)');
 959            $db->bind($stmt,1); $db->bind($stmt,2); $db->bind($stmt,3); 
 960            $db->execute($stmt);
 961      */ 
 962  	function _query($sql,$inputarr)
 963      {
 964          if (is_array($sql)) { // is prepared sql
 965              $stmt = $sql[1];
 966              
 967              // we try to bind to permanent array, so that OCIBindByName is persistent
 968              // and carried out once only - note that max array element size is 4000 chars
 969              if (is_array($inputarr)) {
 970                  $bindpos = $sql[3];
 971                  if (isset($this->_bind[$bindpos])) {
 972                  // all tied up already
 973                      $bindarr = &$this->_bind[$bindpos];
 974                  } else {
 975                  // one statement to bind them all
 976                      $bindarr = array();
 977                      foreach($inputarr as $k => $v) {
 978                          $bindarr[$k] = $v;
 979                          OCIBindByName($stmt,":$k",$bindarr[$k],is_string($v) && strlen($v)>4000 ? -1 : 4000);
 980                      }
 981                      $this->_bind[$bindpos] = &$bindarr;
 982                  }
 983              }
 984          } else {
 985              $stmt=OCIParse($this->_connectionID,$sql);
 986          }
 987              
 988          $this->_stmt = $stmt;
 989          if (!$stmt) return false;
 990      
 991          if (defined('ADODB_PREFETCH_ROWS')) @OCISetPrefetch($stmt,ADODB_PREFETCH_ROWS);
 992              
 993          if (is_array($inputarr)) {
 994              foreach($inputarr as $k => $v) {
 995                  if (is_array($v)) {
 996                      if (sizeof($v) == 2) // suggested by g.giunta@libero.
 997                          OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]);
 998                      else
 999                          OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]);
1000                      
1001                      if ($this->debug==99) echo "name=:$k",' var='.$inputarr[$k][0],' len='.$v[1],' type='.$v[2],'<br>';
1002                  } else {
1003                      $len = -1;
1004                      if ($v === ' ') $len = 1;
1005                      if (isset($bindarr)) {    // is prepared sql, so no need to ocibindbyname again
1006                          $bindarr[$k] = $v;
1007                      } else {                 // dynamic sql, so rebind every time
1008                          OCIBindByName($stmt,":$k",$inputarr[$k],$len);
1009                      }
1010                  }
1011              }
1012          }
1013          
1014          $this->_errorMsg = false;
1015          $this->_errorCode = false;
1016          if (OCIExecute($stmt,$this->_commit)) {
1017  //OCIInternalDebug(1);            
1018              if (count($this -> _refLOBs) > 0) {
1019          
1020                  foreach ($this -> _refLOBs as $key => $value) {
1021                      if ($this -> _refLOBs[$key]['TYPE'] == true) {
1022                          $tmp = $this -> _refLOBs[$key]['LOB'] -> load();
1023                          if ($this -> debug) {
1024                              ADOConnection::outp("<b>OUT LOB</b>: LOB has been loaded. <br>");
1025                          }
1026                          //$_GLOBALS[$this -> _refLOBs[$key]['VAR']] = $tmp;
1027                          $this -> _refLOBs[$key]['VAR'] = $tmp;
1028                      } else {
1029                          $this->_refLOBs[$key]['LOB']->save($this->_refLOBs[$key]['VAR']);
1030                          $this -> _refLOBs[$key]['LOB']->free();
1031                          unset($this -> _refLOBs[$key]);
1032                          if ($this->debug) {
1033                              ADOConnection::outp("<b>IN LOB</b>: LOB has been saved. <br>");
1034                          }
1035                      }                    
1036                  }
1037              }
1038          
1039              switch (@OCIStatementType($stmt)) {
1040                  case "SELECT":
1041                      return $stmt;
1042                  
1043                  case 'DECLARE':
1044                  case "BEGIN":
1045                      if (is_array($sql) && !empty($sql[4])) {
1046                          $cursor = $sql[4];
1047                          if (is_resource($cursor)) {
1048                              $ok = OCIExecute($cursor);    
1049                              return $cursor;
1050                          }
1051                          return $stmt;
1052                      } else {
1053                          if (is_resource($stmt)) {
1054                              OCIFreeStatement($stmt);
1055                              return true;
1056                          }
1057                          return $stmt;
1058                      }
1059                      break;
1060                  default :
1061                      // ociclose -- no because it could be used in a LOB?
1062                      return true;
1063              }
1064          }
1065          return false;
1066      }
1067      
1068      // returns true or false
1069  	function _close()
1070      {
1071          if (!$this->_connectionID) return;
1072          
1073          if (!$this->autoCommit) OCIRollback($this->_connectionID);
1074          if (count($this->_refLOBs) > 0) {
1075              foreach ($this ->_refLOBs as $key => $value) {
1076                  $this->_refLOBs[$key]['LOB']->free();
1077                  unset($this->_refLOBs[$key]);
1078              }
1079          }
1080          OCILogoff($this->_connectionID);
1081          
1082          $this->_stmt = false;
1083          $this->_connectionID = false;
1084      }
1085      
1086  	function MetaPrimaryKeys($table, $owner=false,$internalKey=false)
1087      {
1088          if ($internalKey) return array('ROWID');
1089          
1090      // tested with oracle 8.1.7
1091          $table = strtoupper($table);
1092          if ($owner) {
1093              $owner_clause = "AND ((a.OWNER = b.OWNER) AND (a.OWNER = UPPER('$owner')))";
1094              $ptab = 'ALL_';
1095          } else {
1096              $owner_clause = '';
1097              $ptab = 'USER_';
1098          }
1099          $sql = "
1100  SELECT /*+ RULE */ distinct b.column_name
1101     FROM {$ptab}CONSTRAINTS a
1102        , {$ptab}CONS_COLUMNS b
1103    WHERE ( UPPER(b.table_name) = ('$table'))
1104      AND (UPPER(a.table_name) = ('$table') and a.constraint_type = 'P')
1105      $owner_clause
1106      AND (a.constraint_name = b.constraint_name)";
1107  
1108           $rs = $this->Execute($sql);
1109          if ($rs && !$rs->EOF) {
1110              $arr =& $rs->GetArray();
1111              $a = array();
1112              foreach($arr as $v) {
1113                  $a[] = reset($v);
1114              }
1115              return $a;
1116          }
1117          else return false;
1118      }
1119      
1120      // http://gis.mit.edu/classes/11.521/sqlnotes/referential_integrity.html
1121  	function MetaForeignKeys($table, $owner=false)
1122      {
1123      global $ADODB_FETCH_MODE;
1124      
1125          $save = $ADODB_FETCH_MODE;
1126          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
1127          $table = $this->qstr(strtoupper($table));
1128          if (!$owner) {
1129              $owner = $this->user;
1130              $tabp = 'user_';
1131          } else
1132              $tabp = 'all_';
1133              
1134          $owner = ' and owner='.$this->qstr(strtoupper($owner));
1135          
1136          $sql = 
1137  "select constraint_name,r_owner,r_constraint_name 
1138      from {$tabp}constraints
1139      where constraint_type = 'R' and table_name = $table $owner";
1140          
1141          $constraints =& $this->GetArray($sql);
1142          $arr = false;
1143          foreach($constraints as $constr) {
1144              $cons = $this->qstr($constr[0]);
1145              $rowner = $this->qstr($constr[1]);
1146              $rcons = $this->qstr($constr[2]);
1147              $cols = $this->GetArray("select column_name from {$tabp}cons_columns where constraint_name=$cons $owner order by position");
1148              $tabcol = $this->GetArray("select table_name,column_name from {$tabp}cons_columns where owner=$rowner and constraint_name=$rcons order by position");
1149              
1150              if ($cols && $tabcol) 
1151                  for ($i=0, $max=sizeof($cols); $i < $max; $i++) {
1152                      $arr[$tabcol[$i][0]] = $cols[$i][0].'='.$tabcol[$i][1];
1153                  }
1154          }
1155          $ADODB_FETCH_MODE = $save;
1156          
1157          return $arr;
1158      }
1159  
1160      
1161  	function CharMax()
1162      {
1163          return 4000;
1164      }
1165      
1166  	function TextMax()
1167      {
1168          return 4000;
1169      }
1170      
1171      /**
1172       * Quotes a string.
1173       * An example is  $db->qstr("Don't bother",magic_quotes_runtime());
1174       * 
1175       * @param s            the string to quote
1176       * @param [magic_quotes]    if $s is GET/POST var, set to get_magic_quotes_gpc().
1177       *                This undoes the stupidity of magic quotes for GPC.
1178       *
1179       * @return  quoted string to be sent back to database
1180       */
1181  	function qstr($s,$magic_quotes=false)
1182      {    
1183          //$nofixquotes=false;
1184      
1185          if ($this->noNullStrings && strlen($s)==0)$s = ' ';
1186          if (!$magic_quotes) {    
1187              if ($this->replaceQuote[0] == '\\'){
1188                  $s = str_replace('\\','\\\\',$s);
1189              }
1190              return  "'".str_replace("'",$this->replaceQuote,$s)."'";
1191          }
1192          
1193          // undo magic quotes for "
1194          $s = str_replace('\\"','"',$s);
1195          
1196          $s = str_replace('\\\\','\\',$s);
1197          return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
1198          
1199      }
1200      
1201  }
1202  
1203  /*--------------------------------------------------------------------------------------
1204           Class Name: Recordset
1205  --------------------------------------------------------------------------------------*/
1206  
1207  class ADORecordset_oci8 extends ADORecordSet {
1208  
1209      var $databaseType = 'oci8';
1210      var $bind=false;
1211      var $_fieldobjs;
1212      
1213      //var $_arr = false;
1214          
1215  	function ADORecordset_oci8($queryID,$mode=false)
1216      {
1217          if ($mode === false) { 
1218              global $ADODB_FETCH_MODE;
1219              $mode = $ADODB_FETCH_MODE;
1220          }
1221          switch ($mode)
1222          {
1223          case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1224          case ADODB_FETCH_DEFAULT:
1225          case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1226          case ADODB_FETCH_NUM: 
1227          default:
1228          $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1229          }
1230          
1231          $this->adodbFetchMode = $mode;
1232          $this->_queryID = $queryID;
1233      }
1234  
1235  
1236  	function Init()
1237      {
1238          if ($this->_inited) return;
1239          
1240          $this->_inited = true;
1241          if ($this->_queryID) {
1242              
1243              $this->_currentRow = 0;
1244              @$this->_initrs();
1245              $this->EOF = !$this->_fetch();
1246              
1247              /*
1248              // based on idea by Gaetano Giunta to detect unusual oracle errors
1249              // see http://phplens.com/lens/lensforum/msgs.php?id=6771
1250              $err = OCIError($this->_queryID);
1251              if ($err && $this->connection->debug) ADOConnection::outp($err);
1252              */
1253              
1254              if (!is_array($this->fields)) {
1255                  $this->_numOfRows = 0;
1256                  $this->fields = array();
1257              }
1258          } else {
1259              $this->fields = array();
1260              $this->_numOfRows = 0;
1261              $this->_numOfFields = 0;
1262              $this->EOF = true;
1263          }
1264      }
1265      
1266  	function _initrs()
1267      {
1268          $this->_numOfRows = -1;
1269          $this->_numOfFields = OCInumcols($this->_queryID);
1270          if ($this->_numOfFields>0) {
1271              $this->_fieldobjs = array();
1272              $max = $this->_numOfFields;
1273              for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i);
1274          }
1275      }
1276  
1277        /*        Returns: an object containing field information.
1278                Get column information in the Recordset object. fetchField() can be used in order to obtain information about
1279                fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
1280                fetchField() is retrieved.        */
1281  
1282      function &_FetchField($fieldOffset = -1)
1283      {
1284          $fld = new ADOFieldObject;
1285          $fieldOffset += 1;
1286          $fld->name =OCIcolumnname($this->_queryID, $fieldOffset);
1287          $fld->type = OCIcolumntype($this->_queryID, $fieldOffset);
1288          $fld->max_length = OCIcolumnsize($this->_queryID, $fieldOffset);
1289           if ($fld->type == 'NUMBER') {
1290               $p = OCIColumnPrecision($this->_queryID, $fieldOffset);
1291              $sc = OCIColumnScale($this->_queryID, $fieldOffset);
1292              if ($p != 0 && $sc == 0) $fld->type = 'INT';
1293              //echo " $this->name ($p.$sc) ";
1294           }
1295          return $fld;
1296      }
1297      
1298      /* For some reason, OCIcolumnname fails when called after _initrs() so we cache it */
1299      function &FetchField($fieldOffset = -1)
1300      {
1301          return $this->_fieldobjs[$fieldOffset];
1302      }
1303      
1304      
1305      /*
1306      // 10% speedup to move MoveNext to child class
1307      function _MoveNext() 
1308      {
1309      //global $ADODB_EXTENSION;if ($ADODB_EXTENSION) return @adodb_movenext($this);
1310          
1311          if ($this->EOF) return false;
1312          
1313          $this->_currentRow++;
1314          if(@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode))
1315              return true;
1316          $this->EOF = true;
1317          
1318          return false;
1319      }    */
1320      
1321      
1322  	function MoveNext()
1323      {
1324          if (@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) {
1325              $this->_currentRow += 1;
1326              return true;
1327          }
1328          if (!$this->EOF) {
1329              $this->_currentRow += 1;
1330              $this->EOF = true;
1331          }
1332          return false;
1333      }
1334      
1335      /*
1336      # does not work as first record is retrieved in _initrs(), so is not included in GetArray()
1337      function &GetArray($nRows = -1) 
1338      {
1339      global $ADODB_OCI8_GETARRAY;
1340      
1341          if (true ||  !empty($ADODB_OCI8_GETARRAY)) {
1342              # does not support $ADODB_ANSI_PADDING_OFF
1343      
1344              //OCI_RETURN_NULLS and OCI_RETURN_LOBS is set by OCIfetchstatement
1345              switch($this->adodbFetchMode) {
1346              case ADODB_FETCH_NUM:
1347              
1348                  $ncols = @OCIfetchstatement($this->_queryID, $results, 0, $nRows, OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM);
1349                  $results = array_merge(array($this->fields),$results);
1350                  return $results;
1351                  
1352              case ADODB_FETCH_ASSOC: 
1353                  if (ADODB_ASSOC_CASE != 2 || $this->databaseType != 'oci8') break;
1354                  
1355                  $ncols = @OCIfetchstatement($this->_queryID, $assoc, 0, $nRows, OCI_FETCHSTATEMENT_BY_ROW);
1356                  $results =& array_merge(array($this->fields),$assoc);
1357                  return $results;
1358              
1359              default:
1360                  break;
1361              }
1362          }
1363              
1364          $results =& ADORecordSet::GetArray($nRows);
1365          return $results;
1366          
1367      } */
1368      
1369      /* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */
1370      function &GetArrayLimit($nrows,$offset=-1) 
1371      {
1372          if ($offset <= 0) {
1373              $arr =& $this->GetArray($nrows);
1374              return $arr;
1375          }
1376          for ($i=1; $i < $offset; $i++) 
1377              if (!@OCIFetch($this->_queryID)) return array();
1378              
1379          if (!@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) return array();
1380          $results = array();
1381          $cnt = 0;
1382          while (!$this->EOF && $nrows != $cnt) {
1383              $results[$cnt++] = $this->fields;
1384              $this->MoveNext();
1385          }
1386          
1387          return $results;
1388      }
1389  
1390      
1391      /* Use associative array to get fields array */
1392  	function Fields($colname)
1393      {
1394          if (!$this->bind) {
1395              $this->bind = array();
1396              for ($i=0; $i < $this->_numOfFields; $i++) {
1397                  $o = $this->FetchField($i);
1398                  $this->bind[strtoupper($o->name)] = $i;
1399              }
1400          }
1401          
1402           return $this->fields[$this->bind[strtoupper($colname)]];
1403      }
1404      
1405  
1406  
1407  	function _seek($row)
1408      {
1409          return false;
1410      }
1411  
1412  	function _fetch() 
1413      {
1414          return @OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode);
1415      }
1416  
1417      /*        close() only needs to be called if you are worried about using too much memory while your script
1418              is running. All associated result memory for the specified result identifier will automatically be freed.        */
1419  
1420  	function _close() 
1421      {
1422          if ($this->connection->_stmt === $this->_queryID) $this->connection->_stmt = false;
1423          if (!empty($this->_refcursor)) {
1424              OCIFreeCursor($this->_refcursor);
1425              $this->_refcursor = false;
1426          }
1427          @OCIFreeStatement($this->_queryID);
1428           $this->_queryID = false;
1429          
1430      }
1431  
1432  	function MetaType($t,$len=-1)
1433      {
1434          if (is_object($t)) {
1435              $fieldobj = $t;
1436              $t = $fieldobj->type;
1437              $len = $fieldobj->max_length;
1438          }
1439          switch (strtoupper($t)) {
1440           case 'VARCHAR':
1441           case 'VARCHAR2':
1442          case 'CHAR':
1443          case 'VARBINARY':
1444          case 'BINARY':
1445          case 'NCHAR':
1446          case 'NVARCHAR':
1447          case 'NVARCHAR2':
1448                   if (isset($this) && $len <= $this->blobSize) return 'C';
1449          
1450          case 'NCLOB':
1451          case 'LONG':
1452          case 'LONG VARCHAR':
1453          case 'CLOB':
1454          return 'X';
1455          
1456          case 'LONG RAW':
1457          case 'LONG VARBINARY':
1458          case 'BLOB':
1459              return 'B';
1460          
1461          case 'DATE': 
1462              return  ($this->connection->datetime) ? 'T' : 'D';
1463          
1464          
1465          case 'TIMESTAMP': return 'T';
1466          
1467          case 'INT': 
1468          case 'SMALLINT':
1469          case 'INTEGER': 
1470              return 'I';
1471              
1472          default: return 'N';
1473          }
1474      }
1475  }
1476  
1477  class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 {    
1478  	function ADORecordSet_ext_oci8($queryID,$mode=false) 
1479      {
1480          if ($mode === false) { 
1481              global $ADODB_FETCH_MODE;
1482              $mode = $ADODB_FETCH_MODE;
1483          }
1484          switch ($mode)
1485          {
1486          case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1487          case ADODB_FETCH_DEFAULT:
1488          case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1489          case ADODB_FETCH_NUM: 
1490          default: $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1491          }
1492          $this->adodbFetchMode = $mode;
1493          $this->_queryID = $queryID;
1494      }
1495      
1496  	function MoveNext()
1497      {
1498          return adodb_movenext($this);
1499      }
1500  }
1501  ?>


Généré le : Sun Feb 25 10:22:19 2007 par Balluche grâce à PHPXref 0.7