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