source: trunk/phpgwapi/inc/adodb/drivers/adodb-oci8.inc.php @ 2

Revision 2, 36.2 KB checked in by niltonneto, 17 years ago (diff)

Removida todas as tags usadas pelo CVS ($Id, $Source).
Primeira versão no CVS externo.

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