TYPO3 CMS  TYPO3_6-2
adodb-oci8.inc.php
Go to the documentation of this file.
1 <?php
2 /*
3 
4  version V5.19 23-Apr-2014 (c) 2000-2014 John Lim. All rights reserved.
5 
6  Released under both BSD license and Lesser GPL library license.
7  Whenever there is any discrepancy between the two licenses,
8  the BSD license will take precedence.
9 
10  Latest version is available at http://adodb.sourceforge.net
11 
12  Code contributed by George Fourlanos <fou@infomap.gr>
13 
14  13 Nov 2000 jlim - removed all ora_* references.
15 */
16 
17 // security - hide paths
18 if (!defined('ADODB_DIR')) die();
19 
20 /*
21 NLS_Date_Format
22 Allows you to use a date format other than the Oracle Lite default. When a literal
23 character string appears where a date value is expected, the Oracle Lite database
24 tests the string to see if it matches the formats of Oracle, SQL-92, or the value
25 specified for this parameter in the POLITE.INI file. Setting this parameter also
26 defines the default format used in the TO_CHAR or TO_DATE functions when no
27 other format string is supplied.
28 
29 For Oracle the default is dd-mon-yy or dd-mon-yyyy, and for SQL-92 the default is
30 yy-mm-dd or yyyy-mm-dd.
31 
32 Using 'RR' in the format forces two-digit years less than or equal to 49 to be
33 interpreted as years in the 21st century (2000-2049), and years over 50 as years in
34 the 20th century (1950-1999). Setting the RR format as the default for all two-digit
35 year entries allows you to become year-2000 compliant. For example:
36 NLS_DATE_FORMAT='RR-MM-DD'
37 
38 You can also modify the date format using the ALTER SESSION command.
39 */
40 
41 # define the LOB descriptor type for the given type
42 # returns false if no LOB descriptor
43 function oci_lob_desc($type) {
44  switch ($type) {
45  case OCI_B_BFILE: $result = OCI_D_FILE; break;
46  case OCI_B_CFILEE: $result = OCI_D_FILE; break;
47  case OCI_B_CLOB: $result = OCI_D_LOB; break;
48  case OCI_B_BLOB: $result = OCI_D_LOB; break;
49  case OCI_B_ROWID: $result = OCI_D_ROWID; break;
50  default: $result = false; break;
51  }
52  return $result;
53 }
54 
55 class ADODB_oci8 extends ADOConnection {
56  var $databaseType = 'oci8';
57  var $dataProvider = 'oci8';
58  var $replaceQuote = "''"; // string to use to replace quotes
59  var $concat_operator='||';
60  var $sysDate = "TRUNC(SYSDATE)";
61  var $sysTimeStamp = 'SYSDATE'; // requires oracle 9 or later, otherwise use 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') and table_name not like 'BIN\$%'"; // bin$ tables are recycle bin tables
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 $metaColumnsSQL2 = "select column_name,data_type,data_length, data_scale, data_precision,
69  case when nullable = 'Y' then 'NULL'
70  else 'NOT NULL' end as nulls,
71  data_default from all_tab_cols
72  where owner='%s' and table_name='%s' order by column_id"; // when there is a schema
73  var $_bindInputArray = true;
74  var $hasGenID = true;
75  var $_genIDSQL = "SELECT (%s.nextval) FROM DUAL";
76  var $_genSeqSQL = "
77 DECLARE
78  PRAGMA AUTONOMOUS_TRANSACTION;
79 BEGIN
80  execute immediate 'CREATE SEQUENCE %s START WITH %s';
81 END;
82 ";
83 
84  var $_dropSeqSQL = "DROP SEQUENCE %s";
85  var $hasAffectedRows = true;
86  var $random = "abs(mod(DBMS_RANDOM.RANDOM,10000001)/10000000)";
87  var $noNullStrings = false;
88  var $connectSID = false;
89  var $_bind = false;
90  var $_nestedSQL = true;
92  var $_getarray = false; // currently not working
93  var $leftOuter = ''; // oracle wierdness, $col = $value (+) for LEFT OUTER, $col (+)= $value for RIGHT OUTER
94  var $session_sharing_force_blob = false; // alter session on updateblob if set to true
95  var $firstrows = true; // enable first rows optimization on SelectLimit()
96  var $selectOffsetAlg1 = 1000; // when to use 1st algorithm of selectlimit.
97  var $NLS_DATE_FORMAT = 'YYYY-MM-DD'; // To include time, use 'RRRR-MM-DD HH24:MI:SS'
98  var $dateformat = 'YYYY-MM-DD'; // DBDate format
100  var $datetime = false; // MetaType('DATE') returns 'D' (datetime==false) or 'T' (datetime == true)
101  var $_refLOBs = array();
102 
103  // var $ansiOuter = true; // if oracle9
104 
105  function ADODB_oci8()
106  {
107  $this->_hasOciFetchStatement = ADODB_PHPVER >= 0x4200;
108  if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_';
109  }
110 
111  /* function MetaColumns($table, $normalize=true) added by smondino@users.sourceforge.net*/
112  function MetaColumns($table, $normalize=true)
113  {
114  global $ADODB_FETCH_MODE;
115 
116  $schema = '';
117  $this->_findschema($table, $schema);
118 
119  $false = false;
120  $save = $ADODB_FETCH_MODE;
121  $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
122  if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
123 
124  if ($schema)
125  $rs = $this->Execute(sprintf($this->metaColumnsSQL2, strtoupper($schema), strtoupper($table)));
126  else
127  $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
128 
129  if (isset($savem)) $this->SetFetchMode($savem);
130  $ADODB_FETCH_MODE = $save;
131  if (!$rs) {
132  return $false;
133  }
134  $retarr = array();
135  while (!$rs->EOF) {
136  $fld = new ADOFieldObject();
137  $fld->name = $rs->fields[0];
138  $fld->type = $rs->fields[1];
139  $fld->max_length = $rs->fields[2];
140  $fld->scale = $rs->fields[3];
141  if ($rs->fields[1] == 'NUMBER') {
142  if ($rs->fields[3] == 0) $fld->type = 'INT';
143  $fld->max_length = $rs->fields[4];
144  }
145  $fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0);
146  $fld->binary = (strpos($fld->type,'BLOB') !== false);
147  $fld->default_value = $rs->fields[6];
148 
149  if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
150  else $retarr[strtoupper($fld->name)] = $fld;
151  $rs->MoveNext();
152  }
153  $rs->Close();
154  if (empty($retarr))
155  return $false;
156  else
157  return $retarr;
158  }
159 
160  function Time()
161  {
162  $rs = $this->Execute("select TO_CHAR($this->sysTimeStamp,'YYYY-MM-DD HH24:MI:SS') from dual");
163  if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields));
164 
165  return false;
166  }
167 
194  function _connect($argHostname, $argUsername, $argPassword, $argDatabasename=null, $mode=0)
195  {
196  if (!function_exists('oci_pconnect')) return null;
197  #adodb_backtrace();
198 
199  $this->_errorMsg = false;
200  $this->_errorCode = false;
201 
202  if($argHostname) { // added by Jorma Tuomainen <jorma.tuomainen@ppoy.fi>
203  if (empty($argDatabasename)) $argDatabasename = $argHostname;
204  else {
205  if(strpos($argHostname,":")) {
206  $argHostinfo=explode(":",$argHostname);
207  $argHostname=$argHostinfo[0];
208  $argHostport=$argHostinfo[1];
209  } else {
210  $argHostport = empty($this->port)? "1521" : $this->port;
211  }
212 
213  if (strncasecmp($argDatabasename,'SID=',4) == 0) {
214  $argDatabasename = substr($argDatabasename,4);
215  $this->connectSID = true;
216  }
217 
218  if ($this->connectSID) {
219  $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
220  .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))";
221  } else
222  $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
223  .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))";
224  }
225  }
226 
227  //if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>";
228  if ($mode==1) {
229  $this->_connectionID = ($this->charSet)
230  ? oci_pconnect($argUsername,$argPassword, $argDatabasename,$this->charSet)
231  : oci_pconnect($argUsername,$argPassword, $argDatabasename);
232  if ($this->_connectionID && $this->autoRollback) oci_rollback($this->_connectionID);
233  } else if ($mode==2) {
234  $this->_connectionID = ($this->charSet)
235  ? oci_new_connect($argUsername,$argPassword, $argDatabasename,$this->charSet)
236  : oci_new_connect($argUsername,$argPassword, $argDatabasename);
237  } else {
238  $this->_connectionID = ($this->charSet)
239  ? oci_connect($argUsername,$argPassword, $argDatabasename,$this->charSet)
240  : oci_connect($argUsername,$argPassword, $argDatabasename);
241  }
242  if (!$this->_connectionID) {
243  return false;
244  }
245 
246  if ($this->_initdate) {
247  $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='".$this->NLS_DATE_FORMAT."'");
248  }
249 
250  // looks like:
251  // Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production
252  // $vers = oci_server_version($this->_connectionID);
253  // if (strpos($vers,'8i') !== false) $this->ansiOuter = true;
254  return true;
255  }
256 
257  function ServerInfo()
258  {
259  $arr['compat'] = $this->GetOne('select value from sys.database_compatible_level');
260  $arr['description'] = @oci_server_version($this->_connectionID);
261  $arr['version'] = ADOConnection::_findvers($arr['description']);
262  return $arr;
263  }
264  // returns true or false
265  function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
266  {
267  return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,1);
268  }
269 
270  // returns true or false
271  function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
272  {
273  return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,2);
274  }
275 
276  function _affectedrows()
277  {
278  if (is_resource($this->_stmt)) return @oci_num_rows($this->_stmt);
279  return 0;
280  }
281 
282  function IfNull( $field, $ifNull )
283  {
284  return " NVL($field, $ifNull) "; // if Oracle
285  }
286 
287  // format and return date string in database date format
288  function DBDate($d,$isfld=false)
289  {
290  if (empty($d) && $d !== 0) return 'null';
291 
292  if ($isfld) {
293  $d = _adodb_safedate($d);
294  return 'TO_DATE('.$d.",'".$this->dateformat."')";
295  }
296 
297  if (is_string($d)) $d = ADORecordSet::UnixDate($d);
298 
299  if (is_object($d)) $ds = $d->format($this->fmtDate);
300  else $ds = adodb_date($this->fmtDate,$d);
301 
302  return "TO_DATE(".$ds.",'".$this->dateformat."')";
303  }
304 
305  function BindDate($d)
306  {
307  $d = ADOConnection::DBDate($d);
308  if (strncmp($d,"'",1)) return $d;
309 
310  return substr($d,1,strlen($d)-2);
311  }
312 
313  function BindTimeStamp($ts)
314  {
315  if (empty($ts) && $ts !== 0) return 'null';
316  if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
317 
318  if (is_object($ts)) $tss = $ts->format("'Y-m-d H:i:s'");
319  else $tss = adodb_date("'Y-m-d H:i:s'",$ts);
320 
321  return $tss;
322  }
323 
324  // format and return date string in database timestamp format
325  function DBTimeStamp($ts,$isfld=false)
326  {
327  if (empty($ts) && $ts !== 0) return 'null';
328  if ($isfld) return 'TO_DATE(substr('.$ts.",1,19),'RRRR-MM-DD, HH24:MI:SS')";
329  if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
330 
331  if (is_object($ts)) $tss = $ts->format("'Y-m-d H:i:s'");
332  else $tss = date("'Y-m-d H:i:s'",$ts);
333 
334  return 'TO_DATE('.$tss.",'RRRR-MM-DD, HH24:MI:SS')";
335  }
336 
337  function RowLock($tables,$where,$col='1 as adodbignore')
338  {
339  if ($this->autoCommit) $this->BeginTrans();
340  return $this->GetOne("select $col from $tables where $where for update");
341  }
342 
343  function MetaTables($ttype=false,$showSchema=false,$mask=false)
344  {
345  if ($mask) {
346  $save = $this->metaTablesSQL;
347  $mask = $this->qstr(strtoupper($mask));
348  $this->metaTablesSQL .= " AND upper(table_name) like $mask";
349  }
350  $ret = ADOConnection::MetaTables($ttype,$showSchema);
351 
352  if ($mask) {
353  $this->metaTablesSQL = $save;
354  }
355  return $ret;
356  }
357 
358  // Mark Newnham
359  function MetaIndexes ($table, $primary = FALSE, $owner=false)
360  {
361  // save old fetch mode
362  global $ADODB_FETCH_MODE;
363 
364  $save = $ADODB_FETCH_MODE;
365  $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
366 
367  if ($this->fetchMode !== FALSE) {
368  $savem = $this->SetFetchMode(FALSE);
369  }
370 
371  // get index details
372  $table = strtoupper($table);
373 
374  // get Primary index
375  $primary_key = '';
376 
377  $false = false;
378  $rs = $this->Execute(sprintf("SELECT * FROM ALL_CONSTRAINTS WHERE UPPER(TABLE_NAME)='%s' AND CONSTRAINT_TYPE='P'",$table));
379  if (!is_object($rs)) {
380  if (isset($savem))
381  $this->SetFetchMode($savem);
382  $ADODB_FETCH_MODE = $save;
383  return $false;
384  }
385 
386  if ($row = $rs->FetchRow())
387  $primary_key = $row[1]; //constraint_name
388 
389  if ($primary==TRUE && $primary_key=='') {
390  if (isset($savem))
391  $this->SetFetchMode($savem);
392  $ADODB_FETCH_MODE = $save;
393  return $false; //There is no primary key
394  }
395 
396  $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));
397 
398 
399  if (!is_object($rs)) {
400  if (isset($savem))
401  $this->SetFetchMode($savem);
402  $ADODB_FETCH_MODE = $save;
403  return $false;
404  }
405 
406  $indexes = array ();
407  // parse index data into array
408 
409  while ($row = $rs->FetchRow()) {
410  if ($primary && $row[0] != $primary_key) continue;
411  if (!isset($indexes[$row[0]])) {
412  $indexes[$row[0]] = array(
413  'unique' => ($row[1] == 'UNIQUE'),
414  'columns' => array()
415  );
416  }
417  $indexes[$row[0]]['columns'][$row[2] - 1] = $row[3];
418  }
419 
420  // sort columns by order in the index
421  foreach ( array_keys ($indexes) as $index ) {
422  ksort ($indexes[$index]['columns']);
423  }
424 
425  if (isset($savem)) {
426  $this->SetFetchMode($savem);
427  $ADODB_FETCH_MODE = $save;
428  }
429  return $indexes;
430  }
431 
432  function BeginTrans()
433  {
434  if ($this->transOff) return true;
435  $this->transCnt += 1;
436  $this->autoCommit = false;
437  $this->_commit = OCI_DEFAULT;
438 
439  if ($this->_transmode) $ok = $this->Execute("SET TRANSACTION ".$this->_transmode);
440  else $ok = true;
441 
442  return $ok ? true : false;
443  }
444 
445  function CommitTrans($ok=true)
446  {
447  if ($this->transOff) return true;
448  if (!$ok) return $this->RollbackTrans();
449 
450  if ($this->transCnt) $this->transCnt -= 1;
451  $ret = oci_commit($this->_connectionID);
452  $this->_commit = OCI_COMMIT_ON_SUCCESS;
453  $this->autoCommit = true;
454  return $ret;
455  }
456 
457  function RollbackTrans()
458  {
459  if ($this->transOff) return true;
460  if ($this->transCnt) $this->transCnt -= 1;
461  $ret = oci_rollback($this->_connectionID);
462  $this->_commit = OCI_COMMIT_ON_SUCCESS;
463  $this->autoCommit = true;
464  return $ret;
465  }
466 
467 
468  function SelectDB($dbName)
469  {
470  return false;
471  }
472 
473  function ErrorMsg()
474  {
475  if ($this->_errorMsg !== false) return $this->_errorMsg;
476 
477  if (is_resource($this->_stmt)) $arr = @oci_error($this->_stmt);
478  if (empty($arr)) {
479  if (is_resource($this->_connectionID)) $arr = @oci_error($this->_connectionID);
480  else $arr = @oci_error();
481  if ($arr === false) return '';
482  }
483  $this->_errorMsg = $arr['message'];
484  $this->_errorCode = $arr['code'];
485  return $this->_errorMsg;
486  }
487 
488  function ErrorNo()
489  {
490  if ($this->_errorCode !== false) return $this->_errorCode;
491 
492  if (is_resource($this->_stmt)) $arr = @oci_error($this->_stmt);
493  if (empty($arr)) {
494  $arr = @oci_error($this->_connectionID);
495  if ($arr == false) $arr = @oci_error();
496  if ($arr == false) return '';
497  }
498 
499  $this->_errorMsg = $arr['message'];
500  $this->_errorCode = $arr['code'];
501 
502  return $arr['code'];
503  }
504 
508  function SQLDate($fmt, $col=false)
509  {
510  if (!$col) $col = $this->sysTimeStamp;
511  $s = 'TO_CHAR('.$col.",'";
512 
513  $len = strlen($fmt);
514  for ($i=0; $i < $len; $i++) {
515  $ch = $fmt[$i];
516  switch($ch) {
517  case 'Y':
518  case 'y':
519  $s .= 'YYYY';
520  break;
521  case 'Q':
522  case 'q':
523  $s .= 'Q';
524  break;
525 
526  case 'M':
527  $s .= 'Mon';
528  break;
529 
530  case 'm':
531  $s .= 'MM';
532  break;
533  case 'D':
534  case 'd':
535  $s .= 'DD';
536  break;
537 
538  case 'H':
539  $s.= 'HH24';
540  break;
541 
542  case 'h':
543  $s .= 'HH';
544  break;
545 
546  case 'i':
547  $s .= 'MI';
548  break;
549 
550  case 's':
551  $s .= 'SS';
552  break;
553 
554  case 'a':
555  case 'A':
556  $s .= 'AM';
557  break;
558 
559  case 'w':
560  $s .= 'D';
561  break;
562 
563  case 'l':
564  $s .= 'DAY';
565  break;
566 
567  case 'W':
568  $s .= 'WW';
569  break;
570 
571  default:
572  // handle escape characters...
573  if ($ch == '\\') {
574  $i++;
575  $ch = substr($fmt,$i,1);
576  }
577  if (strpos('-/.:;, ',$ch) !== false) $s .= $ch;
578  else $s .= '"'.$ch.'"';
579 
580  }
581  }
582  return $s. "')";
583  }
584 
585  function GetRandRow($sql, $arr = false)
586  {
587  $sql = "SELECT * FROM ($sql ORDER BY dbms_random.value) WHERE rownum = 1";
588 
589  return $this->GetRow($sql,$arr);
590  }
591 
608  function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
609  {
610  // seems that oracle only supports 1 hint comment in 8i
611  if ($this->firstrows) {
612  if ($nrows > 500 && $nrows < 1000) $hint = "FIRST_ROWS($nrows)";
613  else $hint = 'FIRST_ROWS';
614 
615  if (strpos($sql,'/*+') !== false)
616  $sql = str_replace('/*+ ',"/*+$hint ",$sql);
617  else
618  $sql = preg_replace('/^[ \t\n]*select/i',"SELECT /*+$hint*/",$sql);
619  $hint = "/*+ $hint */";
620  } else
621  $hint = '';
622 
623  if ($offset == -1 || ($offset < $this->selectOffsetAlg1 && 0 < $nrows && $nrows < 1000)) {
624  if ($nrows > 0) {
625  if ($offset > 0) $nrows += $offset;
626  //$inputarr['adodb_rownum'] = $nrows;
627  if ($this->databaseType == 'oci8po') {
628  $sql = "select * from (".$sql.") where rownum <= ?";
629  } else {
630  $sql = "select * from (".$sql.") where rownum <= :adodb_offset";
631  }
632  $inputarr['adodb_offset'] = $nrows;
633  $nrows = -1;
634  }
635  // note that $nrows = 0 still has to work ==> no rows returned
636 
637  $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
638  return $rs;
639 
640  } else {
641  // Algorithm by Tomas V V Cox, from PEAR DB oci8.php
642 
643  // Let Oracle return the name of the columns
644  $q_fields = "SELECT * FROM (".$sql.") WHERE NULL = NULL";
645 
646  $false = false;
647  if (! $stmt_arr = $this->Prepare($q_fields)) {
648  return $false;
649  }
650  $stmt = $stmt_arr[1];
651 
652  if (is_array($inputarr)) {
653  foreach($inputarr as $k => $v) {
654  if (is_array($v)) {
655  if (sizeof($v) == 2) // suggested by g.giunta@libero.
656  oci_bind_by_name($stmt,":$k",$inputarr[$k][0],$v[1]);
657  else
658  oci_bind_by_name($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]);
659  } else {
660  $len = -1;
661  if ($v === ' ') $len = 1;
662  if (isset($bindarr)) { // is prepared sql, so no need to oci_bind_by_name again
663  $bindarr[$k] = $v;
664  } else { // dynamic sql, so rebind every time
665  oci_bind_by_name($stmt,":$k",$inputarr[$k],$len);
666  }
667  }
668  }
669  }
670 
671  if (!oci_execute($stmt, OCI_DEFAULT)) {
672  oci_free_statement($stmt);
673  return $false;
674  }
675 
676  $ncols = oci_num_fields($stmt);
677  for ( $i = 1; $i <= $ncols; $i++ ) {
678  $cols[] = '"'.oci_field_name($stmt, $i).'"';
679  }
680  $result = false;
681 
682  oci_free_statement($stmt);
683  $fields = implode(',', $cols);
684  if ($nrows <= 0) $nrows = 999999999999;
685  else $nrows += $offset;
686  $offset += 1; // in Oracle rownum starts at 1
687 
688  if ($this->databaseType == 'oci8po') {
689  $sql = "SELECT $hint $fields FROM".
690  "(SELECT rownum as adodb_rownum, $fields FROM".
691  " ($sql) WHERE rownum <= ?".
692  ") WHERE adodb_rownum >= ?";
693  } else {
694  $sql = "SELECT $hint $fields FROM".
695  "(SELECT rownum as adodb_rownum, $fields FROM".
696  " ($sql) WHERE rownum <= :adodb_nrows".
697  ") WHERE adodb_rownum >= :adodb_offset";
698  }
699  $inputarr['adodb_nrows'] = $nrows;
700  $inputarr['adodb_offset'] = $offset;
701 
702  if ($secs2cache>0) $rs = $this->CacheExecute($secs2cache, $sql,$inputarr);
703  else $rs = $this->Execute($sql,$inputarr);
704  return $rs;
705  }
706  }
707 
726  function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
727  {
728 
729  //if (strlen($val) < 4000) return $this->Execute("UPDATE $table SET $column=:blob WHERE $where",array('blob'=>$val)) != false;
730 
731  switch(strtoupper($blobtype)) {
732  default: ADOConnection::outp("<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
733  case 'BLOB': $type = OCI_B_BLOB; break;
734  case 'CLOB': $type = OCI_B_CLOB; break;
735  }
736 
737  if ($this->databaseType == 'oci8po')
738  $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
739  else
740  $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
741 
742  $desc = oci_new_descriptor($this->_connectionID, OCI_D_LOB);
743  $arr['blob'] = array($desc,-1,$type);
744  if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT');
745  $commit = $this->autoCommit;
746  if ($commit) $this->BeginTrans();
747  $rs = $this->_Execute($sql,$arr);
748  if ($rez = !empty($rs)) $desc->save($val);
749  $desc->free();
750  if ($commit) $this->CommitTrans();
751  if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=FORCE');
752 
753  if ($rez) $rs->Close();
754  return $rez;
755  }
756 
760  function UpdateBlobFile($table,$column,$val,$where,$blobtype='BLOB')
761  {
762  switch(strtoupper($blobtype)) {
763  default: ADOConnection::outp( "<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
764  case 'BLOB': $type = OCI_B_BLOB; break;
765  case 'CLOB': $type = OCI_B_CLOB; break;
766  }
767 
768  if ($this->databaseType == 'oci8po')
769  $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
770  else
771  $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
772 
773  $desc = oci_new_descriptor($this->_connectionID, OCI_D_LOB);
774  $arr['blob'] = array($desc,-1,$type);
775 
776  $this->BeginTrans();
777  $rs = ADODB_oci8::Execute($sql,$arr);
778  if ($rez = !empty($rs)) $desc->savefile($val);
779  $desc->free();
780  $this->CommitTrans();
781 
782  if ($rez) $rs->Close();
783  return $rez;
784  }
785 
793  function Execute($sql,$inputarr=false)
794  {
795  if ($this->fnExecute) {
796  $fn = $this->fnExecute;
797  $ret = $fn($this,$sql,$inputarr);
798  if (isset($ret)) return $ret;
799  }
800  if ($inputarr !== false) {
801  if (!is_array($inputarr)) $inputarr = array($inputarr);
802 
803  $element0 = reset($inputarr);
804  $array2d = $this->bulkBind && is_array($element0) && !is_object(reset($element0));
805 
806  # see http://phplens.com/lens/lensforum/msgs.php?id=18786
807  if ($array2d || !$this->_bindInputArray) {
808 
809  # is_object check because oci8 descriptors can be passed in
810  if ($array2d && $this->_bindInputArray) {
811  if (is_string($sql))
812  $stmt = $this->Prepare($sql);
813  else
814  $stmt = $sql;
815 
816  foreach($inputarr as $arr) {
817  $ret = $this->_Execute($stmt,$arr);
818  if (!$ret) return $ret;
819  }
820  return $ret;
821  } else {
822  $sqlarr = explode(':',$sql);
823  $sql = '';
824  $lastnomatch = -2;
825  #var_dump($sqlarr);echo "<hr>";var_dump($inputarr);echo"<hr>";
826  foreach($sqlarr as $k => $str) {
827  if ($k == 0) { $sql = $str; continue; }
828  // we need $lastnomatch because of the following datetime,
829  // eg. '10:10:01', which causes code to think that there is bind param :10 and :1
830  $ok = preg_match('/^([0-9]*)/', $str, $arr);
831 
832  if (!$ok) $sql .= $str;
833  else {
834  $at = $arr[1];
835  if (isset($inputarr[$at]) || is_null($inputarr[$at])) {
836  if ((strlen($at) == strlen($str) && $k < sizeof($arr)-1)) {
837  $sql .= ':'.$str;
838  $lastnomatch = $k;
839  } else if ($lastnomatch == $k-1) {
840  $sql .= ':'.$str;
841  } else {
842  if (is_null($inputarr[$at])) $sql .= 'null';
843  else $sql .= $this->qstr($inputarr[$at]);
844  $sql .= substr($str, strlen($at));
845  }
846  } else {
847  $sql .= ':'.$str;
848  }
849 
850  }
851  }
852  $inputarr = false;
853  }
854  }
855  $ret = $this->_Execute($sql,$inputarr);
856 
857 
858  } else {
859  $ret = $this->_Execute($sql,false);
860  }
861 
862  return $ret;
863  }
864 
865  /*
866  * Example of usage:
867  * $stmt = $this->Prepare('insert into emp (empno, ename) values (:empno, :ename)');
868  */
869  function Prepare($sql,$cursor=false)
870  {
871  static $BINDNUM = 0;
872 
873  $stmt = oci_parse($this->_connectionID,$sql);
874 
875  if (!$stmt) {
876  $this->_errorMsg = false;
877  $this->_errorCode = false;
878  $arr = @oci_error($this->_connectionID);
879  if ($arr === false) return false;
880 
881  $this->_errorMsg = $arr['message'];
882  $this->_errorCode = $arr['code'];
883  return false;
884  }
885 
886  $BINDNUM += 1;
887 
888  $sttype = @oci_statement_type($stmt);
889  if ($sttype == 'BEGIN' || $sttype == 'DECLARE') {
890  return array($sql,$stmt,0,$BINDNUM, ($cursor) ? oci_new_cursor($this->_connectionID) : false);
891  }
892  return array($sql,$stmt,0,$BINDNUM);
893  }
894 
895  /*
896  Call an oracle stored procedure and returns a cursor variable as a recordset.
897  Concept by Robert Tuttle robert@ud.com
898 
899  Example:
900  Note: we return a cursor variable in :RS2
901  $rs = $db->ExecuteCursor("BEGIN adodb.open_tab(:RS2); END;",'RS2');
902 
903  $rs = $db->ExecuteCursor(
904  "BEGIN :RS2 = adodb.getdata(:VAR1); END;",
905  'RS2',
906  array('VAR1' => 'Mr Bean'));
907 
908  */
909  function ExecuteCursor($sql,$cursorName='rs',$params=false)
910  {
911  if (is_array($sql)) $stmt = $sql;
912  else $stmt = ADODB_oci8::Prepare($sql,true); # true to allocate oci_new_cursor
913 
914  if (is_array($stmt) && sizeof($stmt) >= 5) {
915  $hasref = true;
916  $ignoreCur = false;
917  $this->Parameter($stmt, $ignoreCur, $cursorName, false, -1, OCI_B_CURSOR);
918  if ($params) {
919  foreach($params as $k => $v) {
920  $this->Parameter($stmt,$params[$k], $k);
921  }
922  }
923  } else
924  $hasref = false;
925 
926  $rs = $this->Execute($stmt);
927  if ($rs) {
928  if ($rs->databaseType == 'array') oci_free_cursor($stmt[4]);
929  else if ($hasref) $rs->_refcursor = $stmt[4];
930  }
931  return $rs;
932  }
933 
963  function Bind(&$stmt,&$var,$size=4000,$type=false,$name=false,$isOutput=false)
964  {
965 
966  if (!is_array($stmt)) return false;
967 
968  if (($type == OCI_B_CURSOR) && sizeof($stmt) >= 5) {
969  return oci_bind_by_name($stmt[1],":".$name,$stmt[4],$size,$type);
970  }
971 
972  if ($name == false) {
973  if ($type !== false) $rez = oci_bind_by_name($stmt[1],":".$stmt[2],$var,$size,$type);
974  else $rez = oci_bind_by_name($stmt[1],":".$stmt[2],$var,$size); // +1 byte for null terminator
975  $stmt[2] += 1;
976  } else if (oci_lob_desc($type)) {
977  if ($this->debug) {
978  ADOConnection::outp("<b>Bind</b>: name = $name");
979  }
980  //we have to create a new Descriptor here
981  $numlob = count($this->_refLOBs);
982  $this->_refLOBs[$numlob]['LOB'] = oci_new_descriptor($this->_connectionID, oci_lob_desc($type));
983  $this->_refLOBs[$numlob]['TYPE'] = $isOutput;
984 
985  $tmp = $this->_refLOBs[$numlob]['LOB'];
986  $rez = oci_bind_by_name($stmt[1], ":".$name, $tmp, -1, $type);
987  if ($this->debug) {
988  ADOConnection::outp("<b>Bind</b>: descriptor has been allocated, var (".$name.") binded");
989  }
990 
991  // if type is input then write data to lob now
992  if ($isOutput == false) {
993  $var = $this->BlobEncode($var);
994  $tmp->WriteTemporary($var);
995  $this->_refLOBs[$numlob]['VAR'] = &$var;
996  if ($this->debug) {
997  ADOConnection::outp("<b>Bind</b>: LOB has been written to temp");
998  }
999  } else {
1000  $this->_refLOBs[$numlob]['VAR'] = &$var;
1001  }
1002  $rez = $tmp;
1003  } else {
1004  if ($this->debug)
1005  ADOConnection::outp("<b>Bind</b>: name = $name");
1006 
1007  if ($type !== false) $rez = oci_bind_by_name($stmt[1],":".$name,$var,$size,$type);
1008  else $rez = oci_bind_by_name($stmt[1],":".$name,$var,$size); // +1 byte for null terminator
1009  }
1010 
1011  return $rez;
1012  }
1013 
1014  function Param($name,$type='C')
1015  {
1016  return ':'.$name;
1017  }
1018 
1035  function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)
1036  {
1037  if ($this->debug) {
1038  $prefix = ($isOutput) ? 'Out' : 'In';
1039  $ztype = (empty($type)) ? 'false' : $type;
1040  ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
1041  }
1042  return $this->Bind($stmt,$var,$maxLen,$type,$name,$isOutput);
1043  }
1044 
1060  function _query($sql,$inputarr=false)
1061  {
1062  if (is_array($sql)) { // is prepared sql
1063  $stmt = $sql[1];
1064 
1065  // we try to bind to permanent array, so that oci_bind_by_name is persistent
1066  // and carried out once only - note that max array element size is 4000 chars
1067  if (is_array($inputarr)) {
1068  $bindpos = $sql[3];
1069  if (isset($this->_bind[$bindpos])) {
1070  // all tied up already
1071  $bindarr = $this->_bind[$bindpos];
1072  } else {
1073  // one statement to bind them all
1074  $bindarr = array();
1075  foreach($inputarr as $k => $v) {
1076  $bindarr[$k] = $v;
1077  oci_bind_by_name($stmt,":$k",$bindarr[$k],is_string($v) && strlen($v)>4000 ? -1 : 4000);
1078  }
1079  $this->_bind[$bindpos] = $bindarr;
1080  }
1081  }
1082  } else {
1083  $stmt=oci_parse($this->_connectionID,$sql);
1084  }
1085 
1086  $this->_stmt = $stmt;
1087  if (!$stmt) return false;
1088 
1089  if (defined('ADODB_PREFETCH_ROWS')) @oci_set_prefetch($stmt,ADODB_PREFETCH_ROWS);
1090 
1091  if (is_array($inputarr)) {
1092  foreach($inputarr as $k => $v) {
1093  if (is_array($v)) {
1094  if (sizeof($v) == 2) // suggested by g.giunta@libero.
1095  oci_bind_by_name($stmt,":$k",$inputarr[$k][0],$v[1]);
1096  else
1097  oci_bind_by_name($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]);
1098 
1099  if ($this->debug==99) {
1100  if (is_object($v[0]))
1101  echo "name=:$k",' len='.$v[1],' type='.$v[2],'<br>';
1102  else
1103  echo "name=:$k",' var='.$inputarr[$k][0],' len='.$v[1],' type='.$v[2],'<br>';
1104 
1105  }
1106  } else {
1107  $len = -1;
1108  if ($v === ' ') $len = 1;
1109  if (isset($bindarr)) { // is prepared sql, so no need to oci_bind_by_name again
1110  $bindarr[$k] = $v;
1111  } else { // dynamic sql, so rebind every time
1112  oci_bind_by_name($stmt,":$k",$inputarr[$k],$len);
1113  }
1114  }
1115  }
1116  }
1117 
1118  $this->_errorMsg = false;
1119  $this->_errorCode = false;
1120  if (oci_execute($stmt,$this->_commit)) {
1121 
1122  if (count($this -> _refLOBs) > 0) {
1123 
1124  foreach ($this -> _refLOBs as $key => $value) {
1125  if ($this -> _refLOBs[$key]['TYPE'] == true) {
1126  $tmp = $this -> _refLOBs[$key]['LOB'] -> load();
1127  if ($this -> debug) {
1128  ADOConnection::outp("<b>OUT LOB</b>: LOB has been loaded. <br>");
1129  }
1130  //$_GLOBALS[$this -> _refLOBs[$key]['VAR']] = $tmp;
1131  $this -> _refLOBs[$key]['VAR'] = $tmp;
1132  } else {
1133  $this->_refLOBs[$key]['LOB']->save($this->_refLOBs[$key]['VAR']);
1134  $this -> _refLOBs[$key]['LOB']->free();
1135  unset($this -> _refLOBs[$key]);
1136  if ($this->debug) {
1137  ADOConnection::outp("<b>IN LOB</b>: LOB has been saved. <br>");
1138  }
1139  }
1140  }
1141  }
1142 
1143  switch (@oci_statement_type($stmt)) {
1144  case "SELECT":
1145  return $stmt;
1146 
1147  case 'DECLARE':
1148  case "BEGIN":
1149  if (is_array($sql) && !empty($sql[4])) {
1150  $cursor = $sql[4];
1151  if (is_resource($cursor)) {
1152  $ok = oci_execute($cursor);
1153  return $cursor;
1154  }
1155  return $stmt;
1156  } else {
1157  if (is_resource($stmt)) {
1158  oci_free_statement($stmt);
1159  return true;
1160  }
1161  return $stmt;
1162  }
1163  break;
1164  default :
1165 
1166  return true;
1167  }
1168  }
1169  return false;
1170  }
1171 
1172  // From Oracle Whitepaper: PHP Scalability and High Availability
1173  function IsConnectionError($err)
1174  {
1175  switch($err) {
1176  case 378: /* buffer pool param incorrect */
1177  case 602: /* core dump */
1178  case 603: /* fatal error */
1179  case 609: /* attach failed */
1180  case 1012: /* not logged in */
1181  case 1033: /* init or shutdown in progress */
1182  case 1043: /* Oracle not available */
1183  case 1089: /* immediate shutdown in progress */
1184  case 1090: /* shutdown in progress */
1185  case 1092: /* instance terminated */
1186  case 3113: /* disconnect */
1187  case 3114: /* not connected */
1188  case 3122: /* closing window */
1189  case 3135: /* lost contact */
1190  case 12153: /* TNS: not connected */
1191  case 27146: /* fatal or instance terminated */
1192  case 28511: /* Lost RPC */
1193  return true;
1194  }
1195  return false;
1196  }
1197 
1198  // returns true or false
1199  function _close()
1200  {
1201  if (!$this->_connectionID) return;
1202 
1203  if (!$this->autoCommit) oci_rollback($this->_connectionID);
1204  if (count($this->_refLOBs) > 0) {
1205  foreach ($this ->_refLOBs as $key => $value) {
1206  $this->_refLOBs[$key]['LOB']->free();
1207  unset($this->_refLOBs[$key]);
1208  }
1209  }
1210  oci_close($this->_connectionID);
1211 
1212  $this->_stmt = false;
1213  $this->_connectionID = false;
1214  }
1215 
1216  function MetaPrimaryKeys($table, $owner=false,$internalKey=false)
1217  {
1218  if ($internalKey) return array('ROWID');
1219 
1220  // tested with oracle 8.1.7
1221  $table = strtoupper($table);
1222  if ($owner) {
1223  $owner_clause = "AND ((a.OWNER = b.OWNER) AND (a.OWNER = UPPER('$owner')))";
1224  $ptab = 'ALL_';
1225  } else {
1226  $owner_clause = '';
1227  $ptab = 'USER_';
1228  }
1229  $sql = "
1230 SELECT /*+ RULE */ distinct b.column_name
1231  FROM {$ptab}CONSTRAINTS a
1232  , {$ptab}CONS_COLUMNS b
1233  WHERE ( UPPER(b.table_name) = ('$table'))
1234  AND (UPPER(a.table_name) = ('$table') and a.constraint_type = 'P')
1235  $owner_clause
1236  AND (a.constraint_name = b.constraint_name)";
1237 
1238  $rs = $this->Execute($sql);
1239  if ($rs && !$rs->EOF) {
1240  $arr = $rs->GetArray();
1241  $a = array();
1242  foreach($arr as $v) {
1243  $a[] = reset($v);
1244  }
1245  return $a;
1246  }
1247  else return false;
1248  }
1249 
1260  function MetaForeignKeys($table, $owner=false, $upper=false)
1261  {
1262  global $ADODB_FETCH_MODE;
1263 
1264  $save = $ADODB_FETCH_MODE;
1265  $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
1266  $table = $this->qstr(strtoupper($table));
1267  if (!$owner) {
1268  $owner = $this->user;
1269  $tabp = 'user_';
1270  } else
1271  $tabp = 'all_';
1272 
1273  $owner = ' and owner='.$this->qstr(strtoupper($owner));
1274 
1275  $sql =
1276 "select constraint_name,r_owner,r_constraint_name
1277  from {$tabp}constraints
1278  where constraint_type = 'R' and table_name = $table $owner";
1279 
1280  $constraints = $this->GetArray($sql);
1281  $arr = false;
1282  foreach($constraints as $constr) {
1283  $cons = $this->qstr($constr[0]);
1284  $rowner = $this->qstr($constr[1]);
1285  $rcons = $this->qstr($constr[2]);
1286  $cols = $this->GetArray("select column_name from {$tabp}cons_columns where constraint_name=$cons $owner order by position");
1287  $tabcol = $this->GetArray("select table_name,column_name from {$tabp}cons_columns where owner=$rowner and constraint_name=$rcons order by position");
1288 
1289  if ($cols && $tabcol)
1290  for ($i=0, $max=sizeof($cols); $i < $max; $i++) {
1291  $arr[$tabcol[$i][0]] = $cols[$i][0].'='.$tabcol[$i][1];
1292  }
1293  }
1294  $ADODB_FETCH_MODE = $save;
1295 
1296  return $arr;
1297  }
1298 
1299 
1300  function CharMax()
1301  {
1302  return 4000;
1303  }
1304 
1305  function TextMax()
1306  {
1307  return 4000;
1308  }
1309 
1320  function qstr($s,$magic_quotes=false)
1321  {
1322  //$nofixquotes=false;
1323 
1324  if ($this->noNullStrings && strlen($s)==0)$s = ' ';
1325  if (!$magic_quotes) {
1326  if ($this->replaceQuote[0] == '\\'){
1327  $s = str_replace('\\','\\\\',$s);
1328  }
1329  return "'".str_replace("'",$this->replaceQuote,$s)."'";
1330  }
1331 
1332  // undo magic quotes for " unless sybase is on
1333  if (!ini_get('magic_quotes_sybase')) {
1334  $s = str_replace('\\"','"',$s);
1335  $s = str_replace('\\\\','\\',$s);
1336  return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
1337  } else {
1338  return "'".$s."'";
1339  }
1340  }
1341 
1342 }
1343 
1344 /*--------------------------------------------------------------------------------------
1345  Class Name: Recordset
1346 --------------------------------------------------------------------------------------*/
1347 
1348 class ADORecordset_oci8 extends ADORecordSet {
1349 
1350  var $databaseType = 'oci8';
1351  var $bind=false;
1353 
1354  //var $_arr = false;
1355 
1356  function ADORecordset_oci8($queryID,$mode=false)
1357  {
1358  if ($mode === false) {
1359  global $ADODB_FETCH_MODE;
1360  $mode = $ADODB_FETCH_MODE;
1361  }
1362  switch ($mode)
1363  {
1364  case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1365  case ADODB_FETCH_DEFAULT:
1366  case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1367  case ADODB_FETCH_NUM:
1368  default:
1369  $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1370  }
1371 
1372  $this->adodbFetchMode = $mode;
1373  $this->_queryID = $queryID;
1374  }
1375 
1376 
1377  function Init()
1378  {
1379  if ($this->_inited) return;
1380 
1381  $this->_inited = true;
1382  if ($this->_queryID) {
1383 
1384  $this->_currentRow = 0;
1385  @$this->_initrs();
1386  if ($this->_numOfFields) $this->EOF = !$this->_fetch();
1387  else $this->EOF = true;
1388 
1389  /*
1390  // based on idea by Gaetano Giunta to detect unusual oracle errors
1391  // see http://phplens.com/lens/lensforum/msgs.php?id=6771
1392  $err = oci_error($this->_queryID);
1393  if ($err && $this->connection->debug) ADOConnection::outp($err);
1394  */
1395 
1396  if (!is_array($this->fields)) {
1397  $this->_numOfRows = 0;
1398  $this->fields = array();
1399  }
1400  } else {
1401  $this->fields = array();
1402  $this->_numOfRows = 0;
1403  $this->_numOfFields = 0;
1404  $this->EOF = true;
1405  }
1406  }
1407 
1408  function _initrs()
1409  {
1410  $this->_numOfRows = -1;
1411  $this->_numOfFields = oci_num_fields($this->_queryID);
1412  if ($this->_numOfFields>0) {
1413  $this->_fieldobjs = array();
1414  $max = $this->_numOfFields;
1415  for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i);
1416  }
1417  }
1418 
1427  function _FetchField($fieldOffset = -1)
1428  {
1429  $fld = new ADOFieldObject;
1430  $fieldOffset += 1;
1431  $fld->name =oci_field_name($this->_queryID, $fieldOffset);
1432  $fld->type = oci_field_type($this->_queryID, $fieldOffset);
1433  $fld->max_length = oci_field_size($this->_queryID, $fieldOffset);
1434 
1435  switch($fld->type) {
1436  case 'NUMBER':
1437  $p = oci_field_precision($this->_queryID, $fieldOffset);
1438  $sc = oci_field_scale($this->_queryID, $fieldOffset);
1439  if ($p != 0 && $sc == 0) $fld->type = 'INT';
1440  $fld->scale = $p;
1441  break;
1442 
1443  case 'CLOB':
1444  case 'NCLOB':
1445  case 'BLOB':
1446  $fld->max_length = -1;
1447  break;
1448  }
1449  return $fld;
1450  }
1451 
1452  /* For some reason, oci_field_name fails when called after _initrs() so we cache it */
1453  function FetchField($fieldOffset = -1)
1454  {
1455  return $this->_fieldobjs[$fieldOffset];
1456  }
1457 
1458 
1459 /*
1460  // 10% speedup to move MoveNext to child class
1461  function _MoveNext()
1462  {
1463  //global $ADODB_EXTENSION;if ($ADODB_EXTENSION) return @adodb_movenext($this);
1464 
1465  if ($this->EOF) return false;
1466 
1467  $this->_currentRow++;
1468  if($this->fields = @oci_fetch_array($this->_queryID,$this->fetchMode))
1469  return true;
1470  $this->EOF = true;
1471 
1472  return false;
1473  }
1474 */
1475 
1476 
1477  function MoveNext()
1478  {
1479  if ($this->fields = @oci_fetch_array($this->_queryID,$this->fetchMode)) {
1480  $this->_currentRow += 1;
1481  return true;
1482  }
1483  if (!$this->EOF) {
1484  $this->_currentRow += 1;
1485  $this->EOF = true;
1486  }
1487  return false;
1488  }
1489 
1490 /*
1491  # does not work as first record is retrieved in _initrs(), so is not included in GetArray()
1492  function GetArray($nRows = -1)
1493  {
1494  global $ADODB_OCI8_GETARRAY;
1495 
1496  if (true || !empty($ADODB_OCI8_GETARRAY)) {
1497  # does not support $ADODB_ANSI_PADDING_OFF
1498 
1499  //OCI_RETURN_NULLS and OCI_RETURN_LOBS is set by oci_fetch_all
1500  switch($this->adodbFetchMode) {
1501  case ADODB_FETCH_NUM:
1502 
1503  $ncols = @oci_fetch_all($this->_queryID, $results, 0, $nRows, oci_fetch_all_BY_ROW+OCI_NUM);
1504  $results = array_merge(array($this->fields),$results);
1505  return $results;
1506 
1507  case ADODB_FETCH_ASSOC:
1508  if (ADODB_ASSOC_CASE != 2 || $this->databaseType != 'oci8') break;
1509 
1510  $ncols = @oci_fetch_all($this->_queryID, $assoc, 0, $nRows, oci_fetch_all_BY_ROW);
1511  $results = array_merge(array($this->fields),$assoc);
1512  return $results;
1513 
1514  default:
1515  break;
1516  }
1517  }
1518 
1519  $results = ADORecordSet::GetArray($nRows);
1520  return $results;
1521 
1522  }
1523 */
1524 
1525  // Optimize SelectLimit() by using oci_fetch()
1526  function GetArrayLimit($nrows,$offset=-1)
1527  {
1528  if ($offset <= 0) {
1529  $arr = $this->GetArray($nrows);
1530  return $arr;
1531  }
1532  $arr = array();
1533  for ($i=1; $i < $offset; $i++)
1534  if (!@oci_fetch($this->_queryID)) return $arr;
1535 
1536  if (!$this->fields = @oci_fetch_array($this->_queryID,$this->fetchMode)) return $arr;;
1537  $results = array();
1538  $cnt = 0;
1539  while (!$this->EOF && $nrows != $cnt) {
1540  $results[$cnt++] = $this->fields;
1541  $this->MoveNext();
1542  }
1543 
1544  return $results;
1545  }
1546 
1547 
1548  // Use associative array to get fields array
1549  function Fields($colname)
1550  {
1551  if (!$this->bind) {
1552  $this->bind = array();
1553  for ($i=0; $i < $this->_numOfFields; $i++) {
1554  $o = $this->FetchField($i);
1555  $this->bind[strtoupper($o->name)] = $i;
1556  }
1557  }
1558 
1559  return $this->fields[$this->bind[strtoupper($colname)]];
1560  }
1561 
1562 
1563 
1564  function _seek($row)
1565  {
1566  return false;
1567  }
1568 
1569  function _fetch()
1570  {
1571  return $this->fields = @oci_fetch_array($this->_queryID,$this->fetchMode);
1572  }
1573 
1579  function _close()
1580  {
1581  if ($this->connection->_stmt === $this->_queryID) $this->connection->_stmt = false;
1582  if (!empty($this->_refcursor)) {
1583  oci_free_cursor($this->_refcursor);
1584  $this->_refcursor = false;
1585  }
1586  @oci_free_statement($this->_queryID);
1587  $this->_queryID = false;
1588  }
1589 
1599  function MetaType($t, $len=-1, $fieldobj=false)
1600  {
1601  if (is_object($t)) {
1602  $fieldobj = $t;
1603  $t = $fieldobj->type;
1604  $len = $fieldobj->max_length;
1605  }
1606 
1607  switch (strtoupper($t)) {
1608  case 'VARCHAR':
1609  case 'VARCHAR2':
1610  case 'CHAR':
1611  case 'VARBINARY':
1612  case 'BINARY':
1613  case 'NCHAR':
1614  case 'NVARCHAR':
1615  case 'NVARCHAR2':
1616  if ($len <= $this->blobSize) return 'C';
1617 
1618  case 'NCLOB':
1619  case 'LONG':
1620  case 'LONG VARCHAR':
1621  case 'CLOB':
1622  return 'X';
1623 
1624  case 'LONG RAW':
1625  case 'LONG VARBINARY':
1626  case 'BLOB':
1627  return 'B';
1628 
1629  case 'DATE':
1630  return ($this->connection->datetime) ? 'T' : 'D';
1631 
1632 
1633  case 'TIMESTAMP': return 'T';
1634 
1635  case 'INT':
1636  case 'SMALLINT':
1637  case 'INTEGER':
1638  return 'I';
1639 
1640  default:
1641  return 'N';
1642  }
1643  }
1644 }
1645 
1646 class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 {
1647  function ADORecordSet_ext_oci8($queryID,$mode=false)
1648  {
1649  if ($mode === false) {
1650  global $ADODB_FETCH_MODE;
1651  $mode = $ADODB_FETCH_MODE;
1652  }
1653  switch ($mode)
1654  {
1655  case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1656  case ADODB_FETCH_DEFAULT:
1657  case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1658  case ADODB_FETCH_NUM:
1659  default: $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break;
1660  }
1661  $this->adodbFetchMode = $mode;
1662  $this->_queryID = $queryID;
1663  }
1664 
1665  function MoveNext()
1666  {
1667  return adodb_movenext($this);
1668  }
1669 }
Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false)
MetaTables($ttype=false, $showSchema=false, $mask=false)
UpdateBlob($table, $column, $val, $where, $blobtype='BLOB')
Prepare($sql, $cursor=false)
_query($sql, $inputarr=false)
SelectDB($dbName)
$sql
Definition: server.php:82
ExecuteCursor($sql, $cursorName='rs', $params=false)
MetaForeignKeys($table, $owner=false, $upper=false)
CommitTrans($ok=true)
Bind(&$stmt, &$var, $size=4000, $type=false, $name=false, $isOutput=false)
if(isset($_REQUEST['nrows'])) else $rs
Definition: server.php:92
SelectLimit($sql, $nrows=-1, $offset=-1, $inputarr=false, $secs2cache=0)
IsConnectionError($err)
qstr($s, $magic_quotes=false)
GetRandRow($sql, $arr=false)
MetaType($t, $len=-1, $fieldobj=false)
die
Definition: index.php:6
adodb_date($fmt, $d=false, $is_gmt=false)
_nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
MetaPrimaryKeys($table, $owner=false, $internalKey=false)
_pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
DBDate($d, $isfld=false)
FetchField($fieldOffset=-1)
RowLock($tables, $where, $col='1 as adodbignore')
_connect($argHostname, $argUsername, $argPassword, $argDatabasename=null, $mode=0)
Execute($sql, $inputarr=false)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
ADORecordSet_ext_oci8($queryID, $mode=false)
GetArrayLimit($nrows, $offset=-1)
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel=E_DEBUG)
MetaColumns($table, $normalize=true)
IfNull( $field, $ifNull)
ADORecordset_oci8($queryID, $mode=false)
MetaIndexes($table, $primary=FALSE, $owner=false)
_FetchField($fieldOffset=-1)
Param($name, $type='C')
$useDBDateFormatForTextInput
DBTimeStamp($ts, $isfld=false)
UpdateBlobFile($table, $column, $val, $where, $blobtype='BLOB')
oci_lob_desc($type)
SQLDate($fmt, $col=false)