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