Documentation TYPO3 par Ameos

adodb-oci8.inc.php

00001 <?php
00002 /*
00003 
00004   version V4.93 10 Oct 2006 (c) 2000-2006 John Lim. All rights reserved.
00005 
00006   Released under both BSD license and Lesser GPL library license. 
00007   Whenever there is any discrepancy between the two licenses, 
00008   the BSD license will take precedence.
00009 
00010   Latest version is available at http://adodb.sourceforge.net
00011   
00012   Code contributed by George Fourlanos <fou@infomap.gr>
00013   
00014   13 Nov 2000 jlim - removed all ora_* references.
00015 */
00016 
00017 // security - hide paths
00018 if (!defined('ADODB_DIR')) die();
00019 
00020 /*
00021 NLS_Date_Format
00022 Allows you to use a date format other than the Oracle Lite default. When a literal
00023 character string appears where a date value is expected, the Oracle Lite database
00024 tests the string to see if it matches the formats of Oracle, SQL-92, or the value
00025 specified for this parameter in the POLITE.INI file. Setting this parameter also
00026 defines the default format used in the TO_CHAR or TO_DATE functions when no
00027 other format string is supplied.
00028 
00029 For Oracle the default is dd-mon-yy or dd-mon-yyyy, and for SQL-92 the default is
00030 yy-mm-dd or yyyy-mm-dd.
00031 
00032 Using 'RR' in the format forces two-digit years less than or equal to 49 to be
00033 interpreted as years in the 21st century (2000–2049), and years over 50 as years in
00034 the 20th century (1950–1999). Setting the RR format as the default for all two-digit
00035 year entries allows you to become year-2000 compliant. For example:
00036 NLS_DATE_FORMAT='RR-MM-DD'
00037 
00038 You can also modify the date format using the ALTER SESSION command. 
00039 */
00040 
00041 # define the LOB descriptor type for the given type
00042 # returns false if no LOB descriptor
00043 function oci_lob_desc($type) {
00044         switch ($type) {
00045                 case OCI_B_BFILE: $result = OCI_D_FILE; break;
00046                 case OCI_B_CFILEE: $result = OCI_D_FILE; break;
00047                 case OCI_B_CLOB: $result = OCI_D_LOB; break;
00048                 case OCI_B_BLOB: $result = OCI_D_LOB; break;
00049                 case OCI_B_ROWID: $result = OCI_D_ROWID; break;
00050                 default: $result = false; break;
00051         }
00052         return $result;
00053 }
00054 
00055 class ADODB_oci8 extends ADOConnection {
00056         var $databaseType = 'oci8';
00057         var $dataProvider = 'oci8';
00058         var $replaceQuote = "''"; // string to use to replace quotes
00059         var $concat_operator='||';
00060         var $sysDate = "TRUNC(SYSDATE)";
00061         var $sysTimeStamp = 'SYSDATE';
00062         var $metaDatabasesSQL = "SELECT USERNAME FROM ALL_USERS WHERE USERNAME NOT IN ('SYS','SYSTEM','DBSNMP','OUTLN') ORDER BY 1";
00063         var $_stmt;
00064         var $_commit = OCI_COMMIT_ON_SUCCESS;
00065         var $_initdate = true; // init date to YYYY-MM-DD
00066         var $metaTablesSQL = "select table_name,table_type from cat where table_type in ('TABLE','VIEW') and table_name not like 'BIN\$%'"; // bin$ tables are recycle bin tables
00067         var $metaColumnsSQL = "select cname,coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno"; //changed by smondino@users.sourceforge. net
00068         var $_bindInputArray = true;
00069         var $hasGenID = true;
00070         var $_genIDSQL = "SELECT (%s.nextval) FROM DUAL";
00071         var $_genSeqSQL = "CREATE SEQUENCE %s START WITH %s";
00072         var $_dropSeqSQL = "DROP SEQUENCE %s";
00073         var $hasAffectedRows = true;
00074         var $random = "abs(mod(DBMS_RANDOM.RANDOM,10000001)/10000000)";
00075         var $noNullStrings = false;
00076         var $connectSID = false;
00077         var $_bind = false;
00078         var $_nestedSQL = true;
00079         var $_hasOCIFetchStatement = false;
00080         var $_getarray = false; // currently not working
00081         var $leftOuter = '';  // oracle wierdness, $col = $value (+) for LEFT OUTER, $col (+)= $value for RIGHT OUTER
00082         var $session_sharing_force_blob = false; // alter session on updateblob if set to true 
00083         var $firstrows = true; // enable first rows optimization on SelectLimit()
00084         var $selectOffsetAlg1 = 100; // when to use 1st algorithm of selectlimit.
00085         var $NLS_DATE_FORMAT = 'YYYY-MM-DD';  // To include time, use 'RRRR-MM-DD HH24:MI:SS'
00086         var $useDBDateFormatForTextInput=false;
00087         var $datetime = false; // MetaType('DATE') returns 'D' (datetime==false) or 'T' (datetime == true)
00088         var $_refLOBs = array();
00089         
00090         // var $ansiOuter = true; // if oracle9
00091     
00092         function ADODB_oci8() 
00093         {
00094                 $this->_hasOCIFetchStatement = ADODB_PHPVER >= 0x4200;
00095                 if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_';
00096         }
00097         
00098         /*  Function &MetaColumns($table) added by smondino@users.sourceforge.net*/
00099         function &MetaColumns($table) 
00100         {
00101         global $ADODB_FETCH_MODE;
00102         
00103                 $false = false;
00104                 $save = $ADODB_FETCH_MODE;
00105                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00106                 if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
00107                 
00108                 $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
00109                 
00110                 if (isset($savem)) $this->SetFetchMode($savem);
00111                 $ADODB_FETCH_MODE = $save;
00112                 if (!$rs) {
00113                         return $false;
00114                 }
00115                 $retarr = array();
00116                 while (!$rs->EOF) { //print_r($rs->fields);
00117                         $fld = new ADOFieldObject();
00118                         $fld->name = $rs->fields[0];
00119                         $fld->type = $rs->fields[1];
00120                         $fld->max_length = $rs->fields[2];
00121                         $fld->scale = $rs->fields[3];
00122                         if ($rs->fields[1] == 'NUMBER') {
00123                                 if ($rs->fields[3] == 0) $fld->type = 'INT';
00124                         $fld->max_length = $rs->fields[4];
00125                 }       
00126                         $fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0);
00127                         $fld->binary = (strpos($fld->type,'BLOB') !== false);
00128                         $fld->default_value = $rs->fields[6];
00129                         
00130                         if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;     
00131                         else $retarr[strtoupper($fld->name)] = $fld;
00132                         $rs->MoveNext();
00133                 }
00134                 $rs->Close();
00135                 if (empty($retarr))
00136                         return  $false;
00137                 else 
00138                         return $retarr;
00139         }
00140         
00141         function Time()
00142         {
00143                 $rs =& $this->Execute("select TO_CHAR($this->sysTimeStamp,'YYYY-MM-DD HH24:MI:SS') from dual");
00144                 if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields));
00145                 
00146                 return false;
00147         }
00148  
00149 /*
00150 
00151   Multiple modes of connection are supported:
00152   
00153   a. Local Database
00154     $conn->Connect(false,'scott','tiger');
00155   
00156   b. From tnsnames.ora
00157     $conn->Connect(false,'scott','tiger',$tnsname); 
00158     $conn->Connect($tnsname,'scott','tiger'); 
00159   
00160   c. Server + service name
00161     $conn->Connect($serveraddress,'scott,'tiger',$service_name);
00162   
00163   d. Server + SID
00164         $conn->connectSID = true;
00165         $conn->Connect($serveraddress,'scott,'tiger',$SID);
00166 
00167 
00168 Example TNSName:
00169 ---------------
00170 NATSOFT.DOMAIN =
00171   (DESCRIPTION =
00172         (ADDRESS_LIST =
00173           (ADDRESS = (PROTOCOL = TCP)(HOST = kermit)(PORT = 1523))
00174         )
00175         (CONNECT_DATA =
00176           (SERVICE_NAME = natsoft.domain)
00177         )
00178   )
00179   
00180   There are 3 connection modes, 0 = non-persistent, 1 = persistent, 2 = force new connection
00181         
00182 */
00183         function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$mode=0)
00184         {
00185                 if (!function_exists('OCIPLogon')) return null;
00186                 
00187                 
00188         $this->_errorMsg = false;
00189                 $this->_errorCode = false;
00190                 
00191                 if($argHostname) { // added by Jorma Tuomainen <jorma.tuomainen@ppoy.fi>
00192                         if (empty($argDatabasename)) $argDatabasename = $argHostname;
00193                         else {
00194                                 if(strpos($argHostname,":")) {
00195                                         $argHostinfo=explode(":",$argHostname);
00196                                         $argHostname=$argHostinfo[0];
00197                                         $argHostport=$argHostinfo[1];
00198                                 } else {
00199                                         $argHostport = empty($this->port)?  "1521" : $this->port;
00200                                 }
00201                                 
00202                                 if ($this->connectSID) {
00203                                         $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
00204                                         .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))";
00205                                 } else
00206                                         $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
00207                                         .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))";
00208                         }
00209                 }
00210                                 
00211                 //if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>";
00212                 if ($mode==1) {
00213                         $this->_connectionID = ($this->charSet) ? 
00214                                 OCIPLogon($argUsername,$argPassword, $argDatabasename)
00215                                 :
00216                                 OCIPLogon($argUsername,$argPassword, $argDatabasename, $this->charSet)
00217                                 ;
00218                         if ($this->_connectionID && $this->autoRollback)  OCIrollback($this->_connectionID);
00219                 } else if ($mode==2) {
00220                         $this->_connectionID = ($this->charSet) ? 
00221                                 OCINLogon($argUsername,$argPassword, $argDatabasename)
00222                                 :
00223                                 OCINLogon($argUsername,$argPassword, $argDatabasename, $this->charSet);
00224                                 
00225                 } else {
00226                         $this->_connectionID = ($this->charSet) ? 
00227                                 OCILogon($argUsername,$argPassword, $argDatabasename)
00228                                 :
00229                                 OCILogon($argUsername,$argPassword, $argDatabasename,$this->charSet);
00230                 }
00231                 if (!$this->_connectionID) return false;
00232                 if ($this->_initdate) {
00233                         $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='".$this->NLS_DATE_FORMAT."'");
00234                 }
00235                 
00236                 // looks like: 
00237                 // Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production
00238                 // $vers = OCIServerVersion($this->_connectionID);
00239                 // if (strpos($vers,'8i') !== false) $this->ansiOuter = true;
00240                 return true;
00241         }
00242         
00243         function ServerInfo()
00244         {
00245                 $arr['compat'] = $this->GetOne('select value from sys.database_compatible_level');
00246                 $arr['description'] = @OCIServerVersion($this->_connectionID);
00247                 $arr['version'] = ADOConnection::_findvers($arr['description']);
00248                 return $arr;
00249         }
00250                 // returns true or false
00251         function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
00252         {
00253                 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,1);
00254         }
00255         
00256         // returns true or false
00257         function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
00258         {
00259                 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,2);
00260         }
00261         
00262         function _affectedrows()
00263         {
00264                 if (is_resource($this->_stmt)) return @OCIRowCount($this->_stmt);
00265                 return 0;
00266         }
00267         
00268         function IfNull( $field, $ifNull ) 
00269         {
00270                 return " NVL($field, $ifNull) "; // if Oracle
00271         }
00272         
00273         // format and return date string in database date format
00274         function DBDate($d)
00275         {
00276                 if (empty($d) && $d !== 0) return 'null';
00277                 
00278                 if (is_string($d)) $d = ADORecordSet::UnixDate($d);
00279                 return "TO_DATE(".adodb_date($this->fmtDate,$d).",'".$this->NLS_DATE_FORMAT."')";
00280         }
00281 
00282         function BindDate($d)
00283         {
00284                 $d = ADOConnection::DBDate($d);
00285                 if (strncmp($d,"'",1)) return $d;
00286                 
00287                 return substr($d,1,strlen($d)-2);
00288         }
00289         
00290         function BindTimeStamp($d)
00291         {
00292                 $d = ADOConnection::DBTimeStamp($d);
00293                 if (strncmp($d,"'",1)) return $d;
00294                 
00295                 return substr($d,1,strlen($d)-2);
00296         }
00297         
00298         // format and return date string in database timestamp format
00299         function DBTimeStamp($ts)
00300         {
00301                 if (empty($ts) && $ts !== 0) return 'null';
00302                 if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
00303                 return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'RRRR-MM-DD, HH:MI:SS AM')";
00304         }
00305         
00306         function RowLock($tables,$where,$flds='1 as ignore') 
00307         {
00308                 if ($this->autoCommit) $this->BeginTrans();
00309                 return $this->GetOne("select $flds from $tables where $where for update");
00310         }
00311         
00312         function &MetaTables($ttype=false,$showSchema=false,$mask=false) 
00313         {
00314                 if ($mask) {
00315                         $save = $this->metaTablesSQL;
00316                         $mask = $this->qstr(strtoupper($mask));
00317                         $this->metaTablesSQL .= " AND upper(table_name) like $mask";
00318                 }
00319                 $ret =& ADOConnection::MetaTables($ttype,$showSchema);
00320                 
00321                 if ($mask) {
00322                         $this->metaTablesSQL = $save;
00323                 }
00324                 return $ret;
00325         }
00326         
00327         // Mark Newnham 
00328         function &MetaIndexes ($table, $primary = FALSE, $owner=false)
00329         {
00330         // save old fetch mode
00331         global $ADODB_FETCH_MODE;
00332 
00333         $save = $ADODB_FETCH_MODE;
00334         $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00335 
00336         if ($this->fetchMode !== FALSE) {
00337                $savem = $this->SetFetchMode(FALSE);
00338         }
00339 
00340                 // get index details
00341                 $table = strtoupper($table);
00342 
00343                 // get Primary index
00344                 $primary_key = '';
00345 
00346                 $false = false;
00347                 $rs = $this->Execute(sprintf("SELECT * FROM ALL_CONSTRAINTS WHERE UPPER(TABLE_NAME)='%s' AND CONSTRAINT_TYPE='P'",$table));
00348                 if ($row = $rs->FetchRow())
00349                    $primary_key = $row[1]; //constraint_name
00350 
00351                 if ($primary==TRUE && $primary_key=='') {
00352                          if (isset($savem)) 
00353                 $this->SetFetchMode($savem);
00354                         $ADODB_FETCH_MODE = $save;
00355                         return $false; //There is no primary key
00356                 }
00357 
00358         $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));
00359 
00360                 
00361         if (!is_object($rs)) {
00362                         if (isset($savem)) 
00363                                 $this->SetFetchMode($savem);
00364                         $ADODB_FETCH_MODE = $save;
00365             return $false;
00366         }
00367 
00368                 $indexes = array ();
00369         // parse index data into array
00370 
00371         while ($row = $rs->FetchRow()) {
00372                         if ($primary && $row[0] != $primary_key) continue;
00373             if (!isset($indexes[$row[0]])) {
00374                                 $indexes[$row[0]] = array(
00375                                    'unique' => ($row[1] == 'UNIQUE'),
00376                                    'columns' => array()
00377                                 );
00378             }
00379             $indexes[$row[0]]['columns'][$row[2] - 1] = $row[3];
00380         }
00381 
00382         // sort columns by order in the index
00383         foreach ( array_keys ($indexes) as $index ) {
00384             ksort ($indexes[$index]['columns']);
00385         }
00386 
00387                 if (isset($savem)) { 
00388             $this->SetFetchMode($savem);
00389                         $ADODB_FETCH_MODE = $save;
00390                 }
00391         return $indexes;
00392         }
00393         
00394         function BeginTrans()
00395         {       
00396                 if ($this->transOff) return true;
00397                 $this->transCnt += 1;
00398                 $this->autoCommit = false;
00399                 $this->_commit = OCI_DEFAULT;
00400                 
00401                 if ($this->_transmode) $this->Execute("SET TRANSACTION ".$this->_transmode);
00402                 return true;
00403         }
00404         
00405         function CommitTrans($ok=true) 
00406         { 
00407                 if ($this->transOff) return true;
00408                 if (!$ok) return $this->RollbackTrans();
00409                 
00410                 if ($this->transCnt) $this->transCnt -= 1;
00411                 $ret = OCIcommit($this->_connectionID);
00412                 $this->_commit = OCI_COMMIT_ON_SUCCESS;
00413                 $this->autoCommit = true;
00414                 return $ret;
00415         }
00416         
00417         function RollbackTrans()
00418         {
00419                 if ($this->transOff) return true;
00420                 if ($this->transCnt) $this->transCnt -= 1;
00421                 $ret = OCIrollback($this->_connectionID);
00422                 $this->_commit = OCI_COMMIT_ON_SUCCESS;
00423                 $this->autoCommit = true;
00424                 return $ret;
00425         }
00426         
00427         
00428         function SelectDB($dbName) 
00429         {
00430                 return false;
00431         }
00432 
00433         function ErrorMsg() 
00434         {
00435                 if ($this->_errorMsg !== false) return $this->_errorMsg;
00436 
00437                 if (is_resource($this->_stmt)) $arr = @OCIerror($this->_stmt);
00438                 if (empty($arr)) {
00439                         $arr = @OCIerror($this->_connectionID);
00440                         if ($arr === false) $arr = @OCIError();
00441                         if ($arr === false) return '';
00442                 }
00443                 $this->_errorMsg = $arr['message'];
00444                 $this->_errorCode = $arr['code'];
00445                 return $this->_errorMsg;
00446         }
00447 
00448         function ErrorNo() 
00449         {
00450                 if ($this->_errorCode !== false) return $this->_errorCode;
00451                 
00452                 if (is_resource($this->_stmt)) $arr = @OCIError($this->_stmt);
00453                 if (empty($arr)) {
00454                         $arr = @OCIError($this->_connectionID);
00455                         if ($arr == false) $arr = @OCIError();
00456                         if ($arr == false) return '';
00457                 }
00458                 
00459                 $this->_errorMsg = $arr['message'];
00460                 $this->_errorCode = $arr['code'];
00461                 
00462                 return $arr['code'];
00463         }
00464         
00465         // Format date column in sql string given an input format that understands Y M D
00466         function SQLDate($fmt, $col=false)
00467         {       
00468                 if (!$col) $col = $this->sysTimeStamp;
00469                 $s = 'TO_CHAR('.$col.",'";
00470                 
00471                 $len = strlen($fmt);
00472                 for ($i=0; $i < $len; $i++) {
00473                         $ch = $fmt[$i];
00474                         switch($ch) {
00475                         case 'Y':
00476                         case 'y':
00477                                 $s .= 'YYYY';
00478                                 break;
00479                         case 'Q':
00480                         case 'q':
00481                                 $s .= 'Q';
00482                                 break;
00483                                 
00484                         case 'M':
00485                                 $s .= 'Mon';
00486                                 break;
00487                                 
00488                         case 'm':
00489                                 $s .= 'MM';
00490                                 break;
00491                         case 'D':
00492                         case 'd':
00493                                 $s .= 'DD';
00494                                 break;
00495                         
00496                         case 'H':
00497                                 $s.= 'HH24';
00498                                 break;
00499                                 
00500                         case 'h':
00501                                 $s .= 'HH';
00502                                 break;
00503                                 
00504                         case 'i':
00505                                 $s .= 'MI';
00506                                 break;
00507                         
00508                         case 's':
00509                                 $s .= 'SS';
00510                                 break;
00511                         
00512                         case 'a':
00513                         case 'A':
00514                                 $s .= 'AM';
00515                                 break;
00516                                 
00517                         case 'w':
00518                                 $s .= 'D';
00519                                 break;
00520                                 
00521                         case 'l':
00522                                 $s .= 'DAY';
00523                                 break;
00524                                 
00525                          case 'W':
00526                                 $s .= 'WW';
00527                                 break;
00528                                 
00529                         default:
00530                         // handle escape characters...
00531                                 if ($ch == '\\') {
00532                                         $i++;
00533                                         $ch = substr($fmt,$i,1);
00534                                 }
00535                                 if (strpos('-/.:;, ',$ch) !== false) $s .= $ch;
00536                                 else $s .= '"'.$ch.'"';
00537                                 
00538                         }
00539                 }
00540                 return $s. "')";
00541         }
00542         
00543         
00544         /*
00545         This algorithm makes use of
00546         
00547         a. FIRST_ROWS hint
00548         The FIRST_ROWS hint explicitly chooses the approach to optimize response time, 
00549         that is, minimum resource usage to return the first row. Results will be returned 
00550         as soon as they are identified. 
00551 
00552         b. Uses rownum tricks to obtain only the required rows from a given offset.
00553          As this uses complicated sql statements, we only use this if the $offset >= 100. 
00554          This idea by Tomas V V Cox.
00555          
00556          This implementation does not appear to work with oracle 8.0.5 or earlier. Comment
00557          out this function then, and the slower SelectLimit() in the base class will be used.
00558         */
00559         function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
00560         {
00561                 // seems that oracle only supports 1 hint comment in 8i
00562                 if ($this->firstrows) {
00563                         if (strpos($sql,'/*+') !== false)
00564                                 $sql = str_replace('/*+ ','/*+FIRST_ROWS ',$sql);
00565                         else
00566                                 $sql = preg_replace('/^[ \t\n]*select/i','SELECT /*+FIRST_ROWS*/',$sql);
00567                 }
00568                 
00569                 if ($offset < $this->selectOffsetAlg1) {
00570                         if ($nrows > 0) {       
00571                                 if ($offset > 0) $nrows += $offset;
00572                                 //$inputarr['adodb_rownum'] = $nrows;
00573                                 if ($this->databaseType == 'oci8po') {
00574                                         $sql = "select * from (".$sql.") where rownum <= ?";
00575                                 } else {
00576                                         $sql = "select * from (".$sql.") where rownum <= :adodb_offset";
00577                                 } 
00578                                 $inputarr['adodb_offset'] = $nrows;
00579                                 $nrows = -1;
00580                         }
00581                         // note that $nrows = 0 still has to work ==> no rows returned
00582 
00583                         $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
00584                         return $rs;
00585                         
00586                 } else {
00587                          // Algorithm by Tomas V V Cox, from PEAR DB oci8.php
00588                         
00589                          // Let Oracle return the name of the columns
00590                         $q_fields = "SELECT * FROM (".$sql.") WHERE NULL = NULL";
00591                          
00592                         $false = false;
00593                         if (! $stmt_arr = $this->Prepare($q_fields)) {
00594                                 return $false;
00595                         }
00596                         $stmt = $stmt_arr[1];
00597                          
00598                          if (is_array($inputarr)) {
00599                                 foreach($inputarr as $k => $v) {
00600                                         if (is_array($v)) {
00601                                                 if (sizeof($v) == 2) // suggested by g.giunta@libero.
00602                                                         OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]);
00603                                                 else
00604                                                         OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]);
00605                                         } else {
00606                                                 $len = -1;
00607                                                 if ($v === ' ') $len = 1;
00608                                                 if (isset($bindarr)) {  // is prepared sql, so no need to ocibindbyname again
00609                                                         $bindarr[$k] = $v;
00610                                                 } else {                                // dynamic sql, so rebind every time
00611                                                         OCIBindByName($stmt,":$k",$inputarr[$k],$len);
00612                                                 }
00613                                         }
00614                                 }
00615                         }
00616                         
00617                          if (!OCIExecute($stmt, OCI_DEFAULT)) {
00618                                  OCIFreeStatement($stmt); 
00619                                  return $false;
00620                          }
00621                          
00622                          $ncols = OCINumCols($stmt);
00623                          for ( $i = 1; $i <= $ncols; $i++ ) {
00624                                  $cols[] = '"'.OCIColumnName($stmt, $i).'"';
00625                          }
00626                          $result = false;
00627                         
00628                          OCIFreeStatement($stmt); 
00629                          $fields = implode(',', $cols);
00630                          $nrows += $offset;
00631                          $offset += 1; // in Oracle rownum starts at 1
00632                         
00633                         if ($this->databaseType == 'oci8po') {
00634                                          $sql = "SELECT $fields FROM".
00635                                           "(SELECT rownum as adodb_rownum, $fields FROM".
00636                                           " ($sql) WHERE rownum <= ?".
00637                                           ") WHERE adodb_rownum >= ?";
00638                                 } else {
00639                                          $sql = "SELECT $fields FROM".
00640                                           "(SELECT rownum as adodb_rownum, $fields FROM".
00641                                           " ($sql) WHERE rownum <= :adodb_nrows".
00642                                           ") WHERE adodb_rownum >= :adodb_offset";
00643                                 } 
00644                                 $inputarr['adodb_nrows'] = $nrows;
00645                                 $inputarr['adodb_offset'] = $offset;
00646                                 
00647                         if ($secs2cache>0) $rs =& $this->CacheExecute($secs2cache, $sql,$inputarr);
00648                         else $rs =& $this->Execute($sql,$inputarr);
00649                         return $rs;
00650                 }
00651         
00652         }
00653         
00674         function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
00675         {
00676                 
00677                 //if (strlen($val) < 4000) return $this->Execute("UPDATE $table SET $column=:blob WHERE $where",array('blob'=>$val)) != false;
00678                 
00679                 switch(strtoupper($blobtype)) {
00680                 default: ADOConnection::outp("<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
00681                 case 'BLOB': $type = OCI_B_BLOB; break;
00682                 case 'CLOB': $type = OCI_B_CLOB; break;
00683                 }
00684                 
00685                 if ($this->databaseType == 'oci8po') 
00686                         $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
00687                 else 
00688                         $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
00689                 
00690                 $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB);
00691                 $arr['blob'] = array($desc,-1,$type);
00692                 if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT');
00693                 $commit = $this->autoCommit;
00694                 if ($commit) $this->BeginTrans();
00695                 $rs = $this->_Execute($sql,$arr);
00696                 if ($rez = !empty($rs)) $desc->save($val);
00697                 $desc->free();
00698                 if ($commit) $this->CommitTrans();
00699                 if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=FORCE');
00700                 
00701                 if ($rez) $rs->Close();
00702                 return $rez;
00703         }
00704         
00708         function UpdateBlobFile($table,$column,$val,$where,$blobtype='BLOB')
00709         {
00710                 switch(strtoupper($blobtype)) {
00711                 default: ADOConnection::outp( "<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
00712                 case 'BLOB': $type = OCI_B_BLOB; break;
00713                 case 'CLOB': $type = OCI_B_CLOB; break;
00714                 }
00715                 
00716                 if ($this->databaseType == 'oci8po') 
00717                         $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
00718                 else 
00719                         $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
00720                 
00721                 $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB);
00722                 $arr['blob'] = array($desc,-1,$type);
00723                 
00724                 $this->BeginTrans();
00725                 $rs = ADODB_oci8::Execute($sql,$arr);
00726                 if ($rez = !empty($rs)) $desc->savefile($val);
00727                 $desc->free();
00728                 $this->CommitTrans();
00729                 
00730                 if ($rez) $rs->Close();
00731                 return $rez;
00732         }
00733 
00741         function &Execute($sql,$inputarr=false) 
00742         {
00743                 if ($this->fnExecute) {
00744                         $fn = $this->fnExecute;
00745                         $ret =& $fn($this,$sql,$inputarr);
00746                         if (isset($ret)) return $ret;
00747                 }
00748                 if ($inputarr) {
00749                         #if (!is_array($inputarr)) $inputarr = array($inputarr);
00750                         
00751                         $element0 = reset($inputarr);
00752                         
00753                         # is_object check because oci8 descriptors can be passed in
00754                         if (is_array($element0) && !is_object(reset($element0))) {
00755                                 if (is_string($sql))
00756                                         $stmt = $this->Prepare($sql);
00757                                 else
00758                                         $stmt = $sql;
00759                                         
00760                                 foreach($inputarr as $arr) {
00761                                         $ret =& $this->_Execute($stmt,$arr);
00762                                         if (!$ret) return $ret;
00763                                 }
00764                         } else {
00765                                 $ret =& $this->_Execute($sql,$inputarr);
00766                         }
00767                         
00768                 } else {
00769                         $ret =& $this->_Execute($sql,false);
00770                 }
00771 
00772                 return $ret;
00773         }
00774         
00775         /*
00776                 Example of usage:
00777                 
00778                 $stmt = $this->Prepare('insert into emp (empno, ename) values (:empno, :ename)');
00779         */
00780         function Prepare($sql,$cursor=false)
00781         {
00782         static $BINDNUM = 0;
00783         
00784                 $stmt = OCIParse($this->_connectionID,$sql);
00785 
00786                 if (!$stmt) return false;
00787 
00788                 $BINDNUM += 1;
00789                 
00790                 $sttype = @OCIStatementType($stmt);
00791                 if ($sttype == 'BEGIN' || $sttype == 'DECLARE') {
00792                         return array($sql,$stmt,0,$BINDNUM, ($cursor) ? OCINewCursor($this->_connectionID) : false);
00793                 }
00794                 return array($sql,$stmt,0,$BINDNUM);
00795         }
00796         
00797         /*
00798                 Call an oracle stored procedure and returns a cursor variable as a recordset. 
00799                 Concept by Robert Tuttle robert@ud.com
00800                 
00801                 Example:
00802                         Note: we return a cursor variable in :RS2
00803                         $rs = $db->ExecuteCursor("BEGIN adodb.open_tab(:RS2); END;",'RS2');
00804                         
00805                         $rs = $db->ExecuteCursor(
00806                                 "BEGIN :RS2 = adodb.getdata(:VAR1); END;", 
00807                                 'RS2',
00808                                 array('VAR1' => 'Mr Bean'));
00809                         
00810         */
00811         function &ExecuteCursor($sql,$cursorName='rs',$params=false)
00812         {
00813                 if (is_array($sql)) $stmt = $sql;
00814                 else $stmt = ADODB_oci8::Prepare($sql,true); # true to allocate OCINewCursor
00815         
00816                 if (is_array($stmt) && sizeof($stmt) >= 5) {
00817                         $hasref = true;
00818                         $ignoreCur = false;
00819                         $this->Parameter($stmt, $ignoreCur, $cursorName, false, -1, OCI_B_CURSOR);
00820                         if ($params) {
00821                                 foreach($params as $k => $v) {
00822                                         $this->Parameter($stmt,$params[$k], $k);
00823                                 }
00824                         }
00825                 } else
00826                         $hasref = false;
00827                         
00828                 $rs =& $this->Execute($stmt);
00829                 if ($rs) {
00830                         if ($rs->databaseType == 'array') OCIFreeCursor($stmt[4]);
00831                         else if ($hasref) $rs->_refcursor = $stmt[4];
00832                 }
00833                 return $rs;
00834         }
00835         
00836         /*
00837                 Bind a variable -- very, very fast for executing repeated statements in oracle. 
00838                 Better than using
00839                         for ($i = 0; $i < $max; $i++) { 
00840                                 $p1 = ?; $p2 = ?; $p3 = ?;
00841                                 $this->Execute("insert into table (col0, col1, col2) values (:0, :1, :2)", 
00842                                         array($p1,$p2,$p3));
00843                         }
00844                 
00845                 Usage:
00846                         $stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)");
00847                         $DB->Bind($stmt, $p1);
00848                         $DB->Bind($stmt, $p2);
00849                         $DB->Bind($stmt, $p3);
00850                         for ($i = 0; $i < $max; $i++) { 
00851                                 $p1 = ?; $p2 = ?; $p3 = ?;
00852                                 $DB->Execute($stmt);
00853                         }
00854                         
00855                 Some timings:           
00856                         ** Test table has 3 cols, and 1 index. Test to insert 1000 records
00857                         Time 0.6081s (1644.60 inserts/sec) with direct OCIParse/OCIExecute
00858                         Time 0.6341s (1577.16 inserts/sec) with ADOdb Prepare/Bind/Execute
00859                         Time 1.5533s ( 643.77 inserts/sec) with pure SQL using Execute
00860                         
00861                 Now if PHP only had batch/bulk updating like Java or PL/SQL...
00862         
00863                 Note that the order of parameters differs from OCIBindByName,
00864                 because we default the names to :0, :1, :2
00865         */
00866         function Bind(&$stmt,&$var,$size=4000,$type=false,$name=false,$isOutput=false)
00867         {
00868                 
00869                 if (!is_array($stmt)) return false;
00870         
00871         if (($type == OCI_B_CURSOR) && sizeof($stmt) >= 5) { 
00872             return OCIBindByName($stmt[1],":".$name,$stmt[4],$size,$type);
00873         }
00874         
00875                 if ($name == false) {
00876                         if ($type !== false) $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size,$type);
00877                         else $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size); // +1 byte for null terminator
00878                         $stmt[2] += 1;
00879                 } else if (oci_lob_desc($type)) {
00880                         if ($this->debug) {
00881                                 ADOConnection::outp("<b>Bind</b>: name = $name");
00882                         }
00883             //we have to create a new Descriptor here
00884                         $numlob = count($this->_refLOBs);
00885                 $this->_refLOBs[$numlob]['LOB'] = OCINewDescriptor($this->_connectionID, oci_lob_desc($type));
00886                         $this->_refLOBs[$numlob]['TYPE'] = $isOutput;
00887                         
00888                         $tmp = &$this->_refLOBs[$numlob]['LOB'];
00889                 $rez = OCIBindByName($stmt[1], ":".$name, $tmp, -1, $type);
00890                         if ($this->debug) {
00891                                 ADOConnection::outp("<b>Bind</b>: descriptor has been allocated, var (".$name.") binded");
00892                         }
00893                         
00894                         // if type is input then write data to lob now
00895                         if ($isOutput == false) {
00896                                 $var = $this->BlobEncode($var);
00897                                 $tmp->WriteTemporary($var);
00898                                 $this->_refLOBs[$numlob]['VAR'] = &$var;
00899                                 if ($this->debug) {
00900                                         ADOConnection::outp("<b>Bind</b>: LOB has been written to temp");
00901                                 }
00902                         } else {
00903                                 $this->_refLOBs[$numlob]['VAR'] = &$var;
00904                         }
00905                         $rez = $tmp;
00906                 } else {
00907                         if ($this->debug) 
00908                                 ADOConnection::outp("<b>Bind</b>: name = $name");
00909                         
00910                         if ($type !== false) $rez = OCIBindByName($stmt[1],":".$name,$var,$size,$type);
00911                         else $rez = OCIBindByName($stmt[1],":".$name,$var,$size); // +1 byte for null terminator
00912                 }
00913                 
00914                 return $rez;
00915         }
00916         
00917         function Param($name,$type=false)
00918         {
00919                 return ':'.$name;
00920         }
00921         
00922         /* 
00923         Usage:
00924                 $stmt = $db->Prepare('select * from table where id =:myid and group=:group');
00925                 $db->Parameter($stmt,$id,'myid');
00926                 $db->Parameter($stmt,$group,'group');
00927                 $db->Execute($stmt);
00928                 
00929                 @param $stmt Statement returned by Prepare() or PrepareSP().
00930                 @param $var PHP variable to bind to
00931                 @param $name Name of stored procedure variable name to bind to.
00932                 @param [$isOutput] Indicates direction of parameter 0/false=IN  1=OUT  2= IN/OUT. This is ignored in oci8.
00933                 @param [$maxLen] Holds an maximum length of the variable.
00934                 @param [$type] The data type of $var. Legal values depend on driver.
00935                 
00936                 See OCIBindByName documentation at php.net.
00937         */
00938         function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)
00939         {
00940                         if  ($this->debug) {
00941                                 $prefix = ($isOutput) ? 'Out' : 'In';
00942                                 $ztype = (empty($type)) ? 'false' : $type;
00943                                 ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
00944                         }
00945                         return $this->Bind($stmt,$var,$maxLen,$type,$name,$isOutput);
00946         }
00947         
00948         /*
00949         returns query ID if successful, otherwise false
00950         this version supports:
00951         
00952            1. $db->execute('select * from table');
00953            
00954            2. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)');
00955                   $db->execute($prepared_statement, array(1,2,3));
00956                   
00957            3. $db->execute('insert into table (a,b,c) values (:a,:b,:c)',array('a'=>1,'b'=>2,'c'=>3));
00958            
00959            4. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)');
00960                   $db->bind($stmt,1); $db->bind($stmt,2); $db->bind($stmt,3); 
00961                   $db->execute($stmt);
00962         */ 
00963         function _query($sql,$inputarr)
00964         {
00965                 if (is_array($sql)) { // is prepared sql
00966                         $stmt = $sql[1];
00967                         
00968                         // we try to bind to permanent array, so that OCIBindByName is persistent
00969                         // and carried out once only - note that max array element size is 4000 chars
00970                         if (is_array($inputarr)) {
00971                                 $bindpos = $sql[3];
00972                                 if (isset($this->_bind[$bindpos])) {
00973                                 // all tied up already
00974                                         $bindarr = &$this->_bind[$bindpos];
00975                                 } else {
00976                                 // one statement to bind them all
00977                                         $bindarr = array();
00978                                         foreach($inputarr as $k => $v) {
00979                                                 $bindarr[$k] = $v;
00980                                                 OCIBindByName($stmt,":$k",$bindarr[$k],is_string($v) && strlen($v)>4000 ? -1 : 4000);
00981                                         }
00982                                         $this->_bind[$bindpos] = &$bindarr;
00983                                 }
00984                         }
00985                 } else {
00986                         $stmt=OCIParse($this->_connectionID,$sql);
00987                 }
00988                         
00989                 $this->_stmt = $stmt;
00990                 if (!$stmt) return false;
00991         
00992                 if (defined('ADODB_PREFETCH_ROWS')) @OCISetPrefetch($stmt,ADODB_PREFETCH_ROWS);
00993                         
00994                 if (is_array($inputarr)) {
00995                         foreach($inputarr as $k => $v) {
00996                                 if (is_array($v)) {
00997                                         if (sizeof($v) == 2) // suggested by g.giunta@libero.
00998                                                 OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]);
00999                                         else
01000                                                 OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]);
01001                                         
01002                                         if ($this->debug==99) echo "name=:$k",' var='.$inputarr[$k][0],' len='.$v[1],' type='.$v[2],'<br>';
01003                                 } else {
01004                                         $len = -1;
01005                                         if ($v === ' ') $len = 1;
01006                                         if (isset($bindarr)) {  // is prepared sql, so no need to ocibindbyname again
01007                                                 $bindarr[$k] = $v;
01008                                         } else {                                // dynamic sql, so rebind every time
01009                                                 OCIBindByName($stmt,":$k",$inputarr[$k],$len);
01010                                         }
01011                                 }
01012                         }
01013                 }
01014                 
01015         $this->_errorMsg = false;
01016                 $this->_errorCode = false;
01017                 if (OCIExecute($stmt,$this->_commit)) {
01018 //OCIInternalDebug(1);                  
01019                         if (count($this -> _refLOBs) > 0) {
01020                 
01021                                 foreach ($this -> _refLOBs as $key => $value) {
01022                                         if ($this -> _refLOBs[$key]['TYPE'] == true) {
01023                                                 $tmp = $this -> _refLOBs[$key]['LOB'] -> load();
01024                                                 if ($this -> debug) {
01025                                                         ADOConnection::outp("<b>OUT LOB</b>: LOB has been loaded. <br>");
01026                                                 }
01027                                                 //$_GLOBALS[$this -> _refLOBs[$key]['VAR']] = $tmp;
01028                                                 $this -> _refLOBs[$key]['VAR'] = $tmp;
01029                                         } else {
01030                         $this->_refLOBs[$key]['LOB']->save($this->_refLOBs[$key]['VAR']);
01031                                                 $this -> _refLOBs[$key]['LOB']->free();
01032                                                 unset($this -> _refLOBs[$key]);
01033                         if ($this->debug) {
01034                                                         ADOConnection::outp("<b>IN LOB</b>: LOB has been saved. <br>");
01035                                                 }
01036                     }                                   
01037                                 }
01038                         }
01039                 
01040             switch (@OCIStatementType($stmt)) {
01041                 case "SELECT":
01042                                         return $stmt;
01043                                 
01044                                 case 'DECLARE':
01045                 case "BEGIN":
01046                     if (is_array($sql) && !empty($sql[4])) {
01047                                                 $cursor = $sql[4];
01048                                                 if (is_resource($cursor)) {
01049                                                         $ok = OCIExecute($cursor);      
01050                                 return $cursor;
01051                                                 }
01052                                                 return $stmt;
01053                     } else {
01054                                                 if (is_resource($stmt)) {
01055                                                         OCIFreeStatement($stmt);
01056                                                         return true;
01057                                                 }
01058                         return $stmt;
01059                     }
01060                     break;
01061                 default :
01062                                         // ociclose -- no because it could be used in a LOB?
01063                     return true;
01064             }
01065                 }
01066                 return false;
01067         }
01068         
01069         // returns true or false
01070         function _close()
01071         {
01072                 if (!$this->_connectionID) return;
01073                 
01074                 if (!$this->autoCommit) OCIRollback($this->_connectionID);
01075                 if (count($this->_refLOBs) > 0) {
01076                         foreach ($this ->_refLOBs as $key => $value) {
01077                                 $this->_refLOBs[$key]['LOB']->free();
01078                                 unset($this->_refLOBs[$key]);
01079                         }
01080                 }
01081                 OCILogoff($this->_connectionID);
01082                 
01083                 $this->_stmt = false;
01084                 $this->_connectionID = false;
01085         }
01086         
01087         function MetaPrimaryKeys($table, $owner=false,$internalKey=false)
01088         {
01089                 if ($internalKey) return array('ROWID');
01090                 
01091         // tested with oracle 8.1.7
01092                 $table = strtoupper($table);
01093                 if ($owner) {
01094                         $owner_clause = "AND ((a.OWNER = b.OWNER) AND (a.OWNER = UPPER('$owner')))";
01095                         $ptab = 'ALL_';
01096                 } else {
01097                         $owner_clause = '';
01098                         $ptab = 'USER_';
01099                 }
01100                 $sql = "
01101 SELECT /*+ RULE */ distinct b.column_name
01102    FROM {$ptab}CONSTRAINTS a
01103           , {$ptab}CONS_COLUMNS b
01104   WHERE ( UPPER(b.table_name) = ('$table'))
01105         AND (UPPER(a.table_name) = ('$table') and a.constraint_type = 'P')
01106         $owner_clause
01107         AND (a.constraint_name = b.constraint_name)";
01108 
01109                 $rs = $this->Execute($sql);
01110                 if ($rs && !$rs->EOF) {
01111                         $arr =& $rs->GetArray();
01112                         $a = array();
01113                         foreach($arr as $v) {
01114                                 $a[] = reset($v);
01115                         }
01116                         return $a;
01117                 }
01118                 else return false;
01119         }
01120         
01121         // http://gis.mit.edu/classes/11.521/sqlnotes/referential_integrity.html
01122         function MetaForeignKeys($table, $owner=false)
01123         {
01124         global $ADODB_FETCH_MODE;
01125         
01126                 $save = $ADODB_FETCH_MODE;
01127                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
01128                 $table = $this->qstr(strtoupper($table));
01129                 if (!$owner) {
01130                         $owner = $this->user;
01131                         $tabp = 'user_';
01132                 } else
01133                         $tabp = 'all_';
01134                         
01135                 $owner = ' and owner='.$this->qstr(strtoupper($owner));
01136                 
01137                 $sql = 
01138 "select constraint_name,r_owner,r_constraint_name 
01139         from {$tabp}constraints
01140         where constraint_type = 'R' and table_name = $table $owner";
01141                 
01142                 $constraints =& $this->GetArray($sql);
01143                 $arr = false;
01144                 foreach($constraints as $constr) {
01145                         $cons = $this->qstr($constr[0]);
01146                         $rowner = $this->qstr($constr[1]);
01147                         $rcons = $this->qstr($constr[2]);
01148                         $cols = $this->GetArray("select column_name from {$tabp}cons_columns where constraint_name=$cons $owner order by position");
01149                         $tabcol = $this->GetArray("select table_name,column_name from {$tabp}cons_columns where owner=$rowner and constraint_name=$rcons order by position");
01150                         
01151                         if ($cols && $tabcol) 
01152                                 for ($i=0, $max=sizeof($cols); $i < $max; $i++) {
01153                                         $arr[$tabcol[$i][0]] = $cols[$i][0].'='.$tabcol[$i][1];
01154                                 }
01155                 }
01156                 $ADODB_FETCH_MODE = $save;
01157                 
01158                 return $arr;
01159         }
01160 
01161         
01162         function CharMax()
01163         {
01164                 return 4000;
01165         }
01166         
01167         function TextMax()
01168         {
01169                 return 4000;
01170         }
01171         
01182         function qstr($s,$magic_quotes=false)
01183         {       
01184                 //$nofixquotes=false;
01185         
01186                 if ($this->noNullStrings && strlen($s)==0)$s = ' ';
01187                 if (!$magic_quotes) {   
01188                         if ($this->replaceQuote[0] == '\\'){
01189                                 $s = str_replace('\\','\\\\',$s);
01190                         }
01191                         return  "'".str_replace("'",$this->replaceQuote,$s)."'";
01192                 }
01193                 
01194                 // undo magic quotes for "
01195                 $s = str_replace('\\"','"',$s);
01196                 
01197                 $s = str_replace('\\\\','\\',$s);
01198                 return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
01199                 
01200         }
01201         
01202 }
01203 
01204 /*--------------------------------------------------------------------------------------
01205                  Class Name: Recordset
01206 --------------------------------------------------------------------------------------*/
01207 
01208 class ADORecordset_oci8 extends ADORecordSet {
01209 
01210         var $databaseType = 'oci8';
01211         var $bind=false;
01212         var $_fieldobjs;
01213         
01214         //var $_arr = false;
01215                 
01216         function ADORecordset_oci8($queryID,$mode=false)
01217         {
01218                 if ($mode === false) { 
01219                         global $ADODB_FETCH_MODE;
01220                         $mode = $ADODB_FETCH_MODE;
01221                 }
01222                 switch ($mode)
01223                 {
01224                 case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
01225                 case ADODB_FETCH_DEFAULT:
01226                 case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
01227                 case ADODB_FETCH_NUM: 
01228                 default:
01229                 $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
01230                 }
01231                 
01232                 $this->adodbFetchMode = $mode;
01233                 $this->_queryID = $queryID;
01234         }
01235 
01236 
01237         function Init()
01238         {
01239                 if ($this->_inited) return;
01240                 
01241                 $this->_inited = true;
01242                 if ($this->_queryID) {
01243                         
01244                         $this->_currentRow = 0;
01245                         @$this->_initrs();
01246                         $this->EOF = !$this->_fetch();
01247                         
01248                         /*
01249                         // based on idea by Gaetano Giunta to detect unusual oracle errors
01250                         // see http://phplens.com/lens/lensforum/msgs.php?id=6771
01251                         $err = OCIError($this->_queryID);
01252                         if ($err && $this->connection->debug) ADOConnection::outp($err);
01253                         */
01254                         
01255                         if (!is_array($this->fields)) {
01256                                 $this->_numOfRows = 0;
01257                                 $this->fields = array();
01258                         }
01259                 } else {
01260                         $this->fields = array();
01261                         $this->_numOfRows = 0;
01262                         $this->_numOfFields = 0;
01263                         $this->EOF = true;
01264                 }
01265         }
01266         
01267         function _initrs()
01268         {
01269                 $this->_numOfRows = -1;
01270                 $this->_numOfFields = OCInumcols($this->_queryID);
01271                 if ($this->_numOfFields>0) {
01272                         $this->_fieldobjs = array();
01273                         $max = $this->_numOfFields;
01274                         for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i);
01275                 }
01276         }
01277 
01278           /*            Returns: an object containing field information.
01279                           Get column information in the Recordset object. fetchField() can be used in order to obtain information about
01280                           fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
01281                           fetchField() is retrieved.            */
01282 
01283         function &_FetchField($fieldOffset = -1)
01284         {
01285                 $fld = new ADOFieldObject;
01286                 $fieldOffset += 1;
01287                 $fld->name =OCIcolumnname($this->_queryID, $fieldOffset);
01288                 $fld->type = OCIcolumntype($this->_queryID, $fieldOffset);
01289                 $fld->max_length = OCIcolumnsize($this->_queryID, $fieldOffset);
01290                 if ($fld->type == 'NUMBER') {
01291                         $p = OCIColumnPrecision($this->_queryID, $fieldOffset);
01292                         $sc = OCIColumnScale($this->_queryID, $fieldOffset);
01293                         if ($p != 0 && $sc == 0) $fld->type = 'INT';
01294                         //echo " $this->name ($p.$sc) ";
01295                 }
01296                 return $fld;
01297         }
01298         
01299         /* For some reason, OCIcolumnname fails when called after _initrs() so we cache it */
01300         function &FetchField($fieldOffset = -1)
01301         {
01302                 return $this->_fieldobjs[$fieldOffset];
01303         }
01304         
01305         
01306         /*
01307         // 10% speedup to move MoveNext to child class
01308         function _MoveNext() 
01309         {
01310         //global $ADODB_EXTENSION;if ($ADODB_EXTENSION) return @adodb_movenext($this);
01311                 
01312                 if ($this->EOF) return false;
01313                 
01314                 $this->_currentRow++;
01315                 if(@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode))
01316                         return true;
01317                 $this->EOF = true;
01318                 
01319                 return false;
01320         }       */
01321         
01322         
01323         function MoveNext()
01324         {
01325                 if (@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) {
01326                         $this->_currentRow += 1;
01327                         return true;
01328                 }
01329                 if (!$this->EOF) {
01330                         $this->_currentRow += 1;
01331                         $this->EOF = true;
01332                 }
01333                 return false;
01334         }
01335         
01336         /*
01337         # does not work as first record is retrieved in _initrs(), so is not included in GetArray()
01338         function &GetArray($nRows = -1) 
01339         {
01340         global $ADODB_OCI8_GETARRAY;
01341         
01342                 if (true ||  !empty($ADODB_OCI8_GETARRAY)) {
01343                         # does not support $ADODB_ANSI_PADDING_OFF
01344         
01345                         //OCI_RETURN_NULLS and OCI_RETURN_LOBS is set by OCIfetchstatement
01346                         switch($this->adodbFetchMode) {
01347                         case ADODB_FETCH_NUM:
01348                         
01349                                 $ncols = @OCIfetchstatement($this->_queryID, $results, 0, $nRows, OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM);
01350                                 $results = array_merge(array($this->fields),$results);
01351                                 return $results;
01352                                 
01353                         case ADODB_FETCH_ASSOC: 
01354                                 if (ADODB_ASSOC_CASE != 2 || $this->databaseType != 'oci8') break;
01355                                 
01356                                 $ncols = @OCIfetchstatement($this->_queryID, $assoc, 0, $nRows, OCI_FETCHSTATEMENT_BY_ROW);
01357                                 $results =& array_merge(array($this->fields),$assoc);
01358                                 return $results;
01359                         
01360                         default:
01361                                 break;
01362                         }
01363                 }
01364                         
01365                 $results =& ADORecordSet::GetArray($nRows);
01366                 return $results;
01367                 
01368         } */
01369         
01370         /* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */
01371         function &GetArrayLimit($nrows,$offset=-1) 
01372         {
01373                 if ($offset <= 0) {
01374                         $arr =& $this->GetArray($nrows);
01375                         return $arr;
01376                 }
01377                 for ($i=1; $i < $offset; $i++) 
01378                         if (!@OCIFetch($this->_queryID)) return array();
01379                         
01380                 if (!@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) return array();
01381                 $results = array();
01382                 $cnt = 0;
01383                 while (!$this->EOF && $nrows != $cnt) {
01384                         $results[$cnt++] = $this->fields;
01385                         $this->MoveNext();
01386                 }
01387                 
01388                 return $results;
01389         }
01390 
01391         
01392         /* Use associative array to get fields array */
01393         function Fields($colname)
01394         {
01395                 if (!$this->bind) {
01396                         $this->bind = array();
01397                         for ($i=0; $i < $this->_numOfFields; $i++) {
01398                                 $o = $this->FetchField($i);
01399                                 $this->bind[strtoupper($o->name)] = $i;
01400                         }
01401                 }
01402                 
01403                  return $this->fields[$this->bind[strtoupper($colname)]];
01404         }
01405         
01406 
01407 
01408         function _seek($row)
01409         {
01410                 return false;
01411         }
01412 
01413         function _fetch() 
01414         {
01415                 return @OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode);
01416         }
01417 
01418         /*              close() only needs to be called if you are worried about using too much memory while your script
01419                         is running. All associated result memory for the specified result identifier will automatically be freed.               */
01420 
01421         function _close() 
01422         {
01423                 if ($this->connection->_stmt === $this->_queryID) $this->connection->_stmt = false;
01424                 if (!empty($this->_refcursor)) {
01425                         OCIFreeCursor($this->_refcursor);
01426                         $this->_refcursor = false;
01427                 }
01428                 @OCIFreeStatement($this->_queryID);
01429                 $this->_queryID = false;
01430                 
01431         }
01432 
01433         function MetaType($t,$len=-1)
01434         {
01435                 if (is_object($t)) {
01436                         $fieldobj = $t;
01437                         $t = $fieldobj->type;
01438                         $len = $fieldobj->max_length;
01439                 }
01440                 switch (strtoupper($t)) {
01441                 case 'VARCHAR':
01442                 case 'VARCHAR2':
01443                 case 'CHAR':
01444                 case 'VARBINARY':
01445                 case 'BINARY':
01446                 case 'NCHAR':
01447                 case 'NVARCHAR':
01448                 case 'NVARCHAR2':
01449                                  if (isset($this) && $len <= $this->blobSize) return 'C';
01450                 
01451                 case 'NCLOB':
01452                 case 'LONG':
01453                 case 'LONG VARCHAR':
01454                 case 'CLOB':
01455                 return 'X';
01456                 
01457                 case 'LONG RAW':
01458                 case 'LONG VARBINARY':
01459                 case 'BLOB':
01460                         return 'B';
01461                 
01462                 case 'DATE': 
01463                         return  ($this->connection->datetime) ? 'T' : 'D';
01464                 
01465                 
01466                 case 'TIMESTAMP': return 'T';
01467                 
01468                 case 'INT': 
01469                 case 'SMALLINT':
01470                 case 'INTEGER': 
01471                         return 'I';
01472                         
01473                 default: return 'N';
01474                 }
01475         }
01476 }
01477 
01478 class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 { 
01479         function ADORecordSet_ext_oci8($queryID,$mode=false) 
01480         {
01481                 if ($mode === false) { 
01482                         global $ADODB_FETCH_MODE;
01483                         $mode = $ADODB_FETCH_MODE;
01484                 }
01485                 switch ($mode)
01486                 {
01487                 case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
01488                 case ADODB_FETCH_DEFAULT:
01489                 case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
01490                 case ADODB_FETCH_NUM: 
01491                 default: $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
01492                 }
01493                 $this->adodbFetchMode = $mode;
01494                 $this->_queryID = $queryID;
01495         }
01496         
01497         function MoveNext()
01498         {
01499                 return adodb_movenext($this);
01500         }
01501 }
01502 ?>


Généré par Les experts TYPO3 avec  doxygen 1.4.6