| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 4 version V5.11 5 May 2010 (c) 2000-2010 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 = "CREATE SEQUENCE %s START WITH %s"; 77 var $_dropSeqSQL = "DROP SEQUENCE %s"; 78 var $hasAffectedRows = true; 79 var $random = "abs(mod(DBMS_RANDOM.RANDOM,10000001)/10000000)"; 80 var $noNullStrings = false; 81 var $connectSID = false; 82 var $_bind = false; 83 var $_nestedSQL = true; 84 var $_hasOCIFetchStatement = false; 85 var $_getarray = false; // currently not working 86 var $leftOuter = ''; // oracle wierdness, $col = $value (+) for LEFT OUTER, $col (+)= $value for RIGHT OUTER 87 var $session_sharing_force_blob = false; // alter session on updateblob if set to true 88 var $firstrows = true; // enable first rows optimization on SelectLimit() 89 var $selectOffsetAlg1 = 1000; // when to use 1st algorithm of selectlimit. 90 var $NLS_DATE_FORMAT = 'YYYY-MM-DD'; // To include time, use 'RRRR-MM-DD HH24:MI:SS' 91 var $dateformat = 'YYYY-MM-DD'; // DBDate format 92 var $useDBDateFormatForTextInput=false; 93 var $datetime = false; // MetaType('DATE') returns 'D' (datetime==false) or 'T' (datetime == true) 94 var $_refLOBs = array(); 95 96 // var $ansiOuter = true; // if oracle9 97 98 function ADODB_oci8() 99 { 100 $this->_hasOCIFetchStatement = ADODB_PHPVER >= 0x4200; 101 if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_'; 102 } 103 104 /* function MetaColumns($table, $normalize=true) added by smondino@users.sourceforge.net*/ 105 function MetaColumns($table, $normalize=true) 106 { 107 global $ADODB_FETCH_MODE; 108 109 $schema = ''; 110 $this->_findschema($table, $schema); 111 112 $false = false; 113 $save = $ADODB_FETCH_MODE; 114 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 115 if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); 116 117 if ($schema) 118 $rs = $this->Execute(sprintf($this->metaColumnsSQL2, strtoupper($schema), strtoupper($table))); 119 else 120 $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table))); 121 122 if (isset($savem)) $this->SetFetchMode($savem); 123 $ADODB_FETCH_MODE = $save; 124 if (!$rs) { 125 return $false; 126 } 127 $retarr = array(); 128 while (!$rs->EOF) { 129 $fld = new ADOFieldObject(); 130 $fld->name = $rs->fields[0]; 131 $fld->type = $rs->fields[1]; 132 $fld->max_length = $rs->fields[2]; 133 $fld->scale = $rs->fields[3]; 134 if ($rs->fields[1] == 'NUMBER') { 135 if ($rs->fields[3] == 0) $fld->type = 'INT'; 136 $fld->max_length = $rs->fields[4]; 137 } 138 $fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0); 139 $fld->binary = (strpos($fld->type,'BLOB') !== false); 140 $fld->default_value = $rs->fields[6]; 141 142 if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld; 143 else $retarr[strtoupper($fld->name)] = $fld; 144 $rs->MoveNext(); 145 } 146 $rs->Close(); 147 if (empty($retarr)) 148 return $false; 149 else 150 return $retarr; 151 } 152 153 function Time() 154 { 155 $rs = $this->Execute("select TO_CHAR($this->sysTimeStamp,'YYYY-MM-DD HH24:MI:SS') from dual"); 156 if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields)); 157 158 return false; 159 } 160 161 /* 162 163 Multiple modes of connection are supported: 164 165 a. Local Database 166 $conn->Connect(false,'scott','tiger'); 167 168 b. From tnsnames.ora 169 $conn->Connect(false,'scott','tiger',$tnsname); 170 $conn->Connect($tnsname,'scott','tiger'); 171 172 c. Server + service name 173 $conn->Connect($serveraddress,'scott,'tiger',$service_name); 174 175 d. Server + SID 176 $conn->connectSID = true; 177 $conn->Connect($serveraddress,'scott,'tiger',$SID); 178 179 180 Example TNSName: 181 --------------- 182 NATSOFT.DOMAIN = 183 (DESCRIPTION = 184 (ADDRESS_LIST = 185 (ADDRESS = (PROTOCOL = TCP)(HOST = kermit)(PORT = 1523)) 186 ) 187 (CONNECT_DATA = 188 (SERVICE_NAME = natsoft.domain) 189 ) 190 ) 191 192 There are 3 connection modes, 0 = non-persistent, 1 = persistent, 2 = force new connection 193 194 */ 195 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$mode=0) 196 { 197 if (!function_exists('OCIPLogon')) return null; 198 #adodb_backtrace(); 199 200 $this->_errorMsg = false; 201 $this->_errorCode = false; 202 203 if($argHostname) { // added by Jorma Tuomainen <jorma.tuomainen@ppoy.fi> 204 if (empty($argDatabasename)) $argDatabasename = $argHostname; 205 else { 206 if(strpos($argHostname,":")) { 207 $argHostinfo=explode(":",$argHostname); 208 $argHostname=$argHostinfo[0]; 209 $argHostport=$argHostinfo[1]; 210 } else { 211 $argHostport = empty($this->port)? "1521" : $this->port; 212 } 213 214 if (strncasecmp($argDatabasename,'SID=',4) == 0) { 215 $argDatabasename = substr($argDatabasename,4); 216 $this->connectSID = true; 217 } 218 219 if ($this->connectSID) { 220 $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname 221 .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))"; 222 } else 223 $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname 224 .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))"; 225 } 226 } 227 228 //if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>"; 229 if ($mode==1) { 230 $this->_connectionID = ($this->charSet) ? 231 OCIPLogon($argUsername,$argPassword, $argDatabasename,$this->charSet) 232 : 233 OCIPLogon($argUsername,$argPassword, $argDatabasename) 234 ; 235 if ($this->_connectionID && $this->autoRollback) OCIrollback($this->_connectionID); 236 } else if ($mode==2) { 237 $this->_connectionID = ($this->charSet) ? 238 OCINLogon($argUsername,$argPassword, $argDatabasename,$this->charSet) 239 : 240 OCINLogon($argUsername,$argPassword, $argDatabasename); 241 242 } else { 243 $this->_connectionID = ($this->charSet) ? 244 OCILogon($argUsername,$argPassword, $argDatabasename,$this->charSet) 245 : 246 OCILogon($argUsername,$argPassword, $argDatabasename); 247 } 248 if (!$this->_connectionID) return false; 249 if ($this->_initdate) { 250 $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='".$this->NLS_DATE_FORMAT."'"); 251 } 252 253 // looks like: 254 // Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production 255 // $vers = OCIServerVersion($this->_connectionID); 256 // if (strpos($vers,'8i') !== false) $this->ansiOuter = true; 257 return true; 258 } 259 260 function ServerInfo() 261 { 262 $arr['compat'] = $this->GetOne('select value from sys.database_compatible_level'); 263 $arr['description'] = @OCIServerVersion($this->_connectionID); 264 $arr['version'] = ADOConnection::_findvers($arr['description']); 265 return $arr; 266 } 267 // returns true or false 268 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) 269 { 270 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,1); 271 } 272 273 // returns true or false 274 function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename) 275 { 276 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,2); 277 } 278 279 function _affectedrows() 280 { 281 if (is_resource($this->_stmt)) return @OCIRowCount($this->_stmt); 282 return 0; 283 } 284 285 function IfNull( $field, $ifNull ) 286 { 287 return " NVL($field, $ifNull) "; // if Oracle 288 } 289 290 // format and return date string in database date format 291 function DBDate($d,$isfld=false) 292 { 293 if (empty($d) && $d !== 0) return 'null'; 294 if ($isfld) return 'TO_DATE('.$d.",'".$this->dateformat."')"; 295 296 if (is_string($d)) $d = ADORecordSet::UnixDate($d); 297 298 if (is_object($d)) $ds = $d->format($this->fmtDate); 299 else $ds = adodb_date($this->fmtDate,$d); 300 301 return "TO_DATE(".$ds.",'".$this->dateformat."')"; 302 } 303 304 function BindDate($d) 305 { 306 $d = ADOConnection::DBDate($d); 307 if (strncmp($d,"'",1)) return $d; 308 309 return substr($d,1,strlen($d)-2); 310 } 311 312 function BindTimeStamp($ts) 313 { 314 if (empty($ts) && $ts !== 0) return 'null'; 315 if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts); 316 317 if (is_object($ts)) $tss = $ts->format("'Y-m-d H:i:s'"); 318 else $tss = adodb_date("'Y-m-d H:i:s'",$ts); 319 320 return $tss; 321 } 322 323 // format and return date string in database timestamp format 324 function DBTimeStamp($ts,$isfld=false) 325 { 326 if (empty($ts) && $ts !== 0) return 'null'; 327 if ($isfld) return 'TO_DATE(substr('.$ts.",1,19),'RRRR-MM-DD, HH24:MI:SS')"; 328 if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts); 329 330 if (is_object($ts)) $tss = $ts->format("'Y-m-d H:i:s'"); 331 else $tss = adodb_date("'Y-m-d H:i:s'",$ts); 332 333 return 'TO_DATE('.$tss.",'RRRR-MM-DD, HH24:MI:SS')"; 334 } 335 336 function RowLock($tables,$where,$col='1 as adodbignore') 337 { 338 if ($this->autoCommit) $this->BeginTrans(); 339 return $this->GetOne("select $col from $tables where $where for update"); 340 } 341 342 function MetaTables($ttype=false,$showSchema=false,$mask=false) 343 { 344 if ($mask) { 345 $save = $this->metaTablesSQL; 346 $mask = $this->qstr(strtoupper($mask)); 347 $this->metaTablesSQL .= " AND upper(table_name) like $mask"; 348 } 349 $ret = ADOConnection::MetaTables($ttype,$showSchema); 350 351 if ($mask) { 352 $this->metaTablesSQL = $save; 353 } 354 return $ret; 355 } 356 357 // Mark Newnham 358 function MetaIndexes ($table, $primary = FALSE, $owner=false) 359 { 360 // save old fetch mode 361 global $ADODB_FETCH_MODE; 362 363 $save = $ADODB_FETCH_MODE; 364 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 365 366 if ($this->fetchMode !== FALSE) { 367 $savem = $this->SetFetchMode(FALSE); 368 } 369 370 // get index details 371 $table = strtoupper($table); 372 373 // get Primary index 374 $primary_key = ''; 375 376 $false = false; 377 $rs = $this->Execute(sprintf("SELECT * FROM ALL_CONSTRAINTS WHERE UPPER(TABLE_NAME)='%s' AND CONSTRAINT_TYPE='P'",$table)); 378 if ($row = $rs->FetchRow()) 379 $primary_key = $row[1]; //constraint_name 380 381 if ($primary==TRUE && $primary_key=='') { 382 if (isset($savem)) 383 $this->SetFetchMode($savem); 384 $ADODB_FETCH_MODE = $save; 385 return $false; //There is no primary key 386 } 387 388 $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)); 389 390 391 if (!is_object($rs)) { 392 if (isset($savem)) 393 $this->SetFetchMode($savem); 394 $ADODB_FETCH_MODE = $save; 395 return $false; 396 } 397 398 $indexes = array (); 399 // parse index data into array 400 401 while ($row = $rs->FetchRow()) { 402 if ($primary && $row[0] != $primary_key) continue; 403 if (!isset($indexes[$row[0]])) { 404 $indexes[$row[0]] = array( 405 'unique' => ($row[1] == 'UNIQUE'), 406 'columns' => array() 407 ); 408 } 409 $indexes[$row[0]]['columns'][$row[2] - 1] = $row[3]; 410 } 411 412 // sort columns by order in the index 413 foreach ( array_keys ($indexes) as $index ) { 414 ksort ($indexes[$index]['columns']); 415 } 416 417 if (isset($savem)) { 418 $this->SetFetchMode($savem); 419 $ADODB_FETCH_MODE = $save; 420 } 421 return $indexes; 422 } 423 424 function BeginTrans() 425 { 426 if ($this->transOff) return true; 427 $this->transCnt += 1; 428 $this->autoCommit = false; 429 $this->_commit = OCI_DEFAULT; 430 431 if ($this->_transmode) $ok = $this->Execute("SET TRANSACTION ".$this->_transmode); 432 else $ok = true; 433 434 return $ok ? true : false; 435 } 436 437 function CommitTrans($ok=true) 438 { 439 if ($this->transOff) return true; 440 if (!$ok) return $this->RollbackTrans(); 441 442 if ($this->transCnt) $this->transCnt -= 1; 443 $ret = OCIcommit($this->_connectionID); 444 $this->_commit = OCI_COMMIT_ON_SUCCESS; 445 $this->autoCommit = true; 446 return $ret; 447 } 448 449 function RollbackTrans() 450 { 451 if ($this->transOff) return true; 452 if ($this->transCnt) $this->transCnt -= 1; 453 $ret = OCIrollback($this->_connectionID); 454 $this->_commit = OCI_COMMIT_ON_SUCCESS; 455 $this->autoCommit = true; 456 return $ret; 457 } 458 459 460 function SelectDB($dbName) 461 { 462 return false; 463 } 464 465 function ErrorMsg() 466 { 467 if ($this->_errorMsg !== false) return $this->_errorMsg; 468 469 if (is_resource($this->_stmt)) $arr = @OCIError($this->_stmt); 470 if (empty($arr)) { 471 if (is_resource($this->_connectionID)) $arr = @OCIError($this->_connectionID); 472 else $arr = @OCIError(); 473 if ($arr === false) return ''; 474 } 475 $this->_errorMsg = $arr['message']; 476 $this->_errorCode = $arr['code']; 477 return $this->_errorMsg; 478 } 479 480 function ErrorNo() 481 { 482 if ($this->_errorCode !== false) return $this->_errorCode; 483 484 if (is_resource($this->_stmt)) $arr = @OCIError($this->_stmt); 485 if (empty($arr)) { 486 $arr = @OCIError($this->_connectionID); 487 if ($arr == false) $arr = @OCIError(); 488 if ($arr == false) return ''; 489 } 490 491 $this->_errorMsg = $arr['message']; 492 $this->_errorCode = $arr['code']; 493 494 return $arr['code']; 495 } 496 497 // Format date column in sql string given an input format that understands Y M D 498 function SQLDate($fmt, $col=false) 499 { 500 if (!$col) $col = $this->sysTimeStamp; 501 $s = 'TO_CHAR('.$col.",'"; 502 503 $len = strlen($fmt); 504 for ($i=0; $i < $len; $i++) { 505 $ch = $fmt[$i]; 506 switch($ch) { 507 case 'Y': 508 case 'y': 509 $s .= 'YYYY'; 510 break; 511 case 'Q': 512 case 'q': 513 $s .= 'Q'; 514 break; 515 516 case 'M': 517 $s .= 'Mon'; 518 break; 519 520 case 'm': 521 $s .= 'MM'; 522 break; 523 case 'D': 524 case 'd': 525 $s .= 'DD'; 526 break; 527 528 case 'H': 529 $s.= 'HH24'; 530 break; 531 532 case 'h': 533 $s .= 'HH'; 534 break; 535 536 case 'i': 537 $s .= 'MI'; 538 break; 539 540 case 's': 541 $s .= 'SS'; 542 break; 543 544 case 'a': 545 case 'A': 546 $s .= 'AM'; 547 break; 548 549 case 'w': 550 $s .= 'D'; 551 break; 552 553 case 'l': 554 $s .= 'DAY'; 555 break; 556 557 case 'W': 558 $s .= 'WW'; 559 break; 560 561 default: 562 // handle escape characters... 563 if ($ch == '\\') { 564 $i++; 565 $ch = substr($fmt,$i,1); 566 } 567 if (strpos('-/.:;, ',$ch) !== false) $s .= $ch; 568 else $s .= '"'.$ch.'"'; 569 570 } 571 } 572 return $s. "')"; 573 } 574 575 function GetRandRow($sql, $arr = false) 576 { 577 $sql = "SELECT * FROM ($sql ORDER BY dbms_random.value) WHERE rownum = 1"; 578 579 return $this->GetRow($sql,$arr); 580 } 581 582 /* 583 This algorithm makes use of 584 585 a. FIRST_ROWS hint 586 The FIRST_ROWS hint explicitly chooses the approach to optimize response time, 587 that is, minimum resource usage to return the first row. Results will be returned 588 as soon as they are identified. 589 590 b. Uses rownum tricks to obtain only the required rows from a given offset. 591 As this uses complicated sql statements, we only use this if the $offset >= 100. 592 This idea by Tomas V V Cox. 593 594 This implementation does not appear to work with oracle 8.0.5 or earlier. Comment 595 out this function then, and the slower SelectLimit() in the base class will be used. 596 */ 597 function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) 598 { 599 // seems that oracle only supports 1 hint comment in 8i 600 if ($this->firstrows) { 601 if (strpos($sql,'/*+') !== false) 602 $sql = str_replace('/*+ ','/*+FIRST_ROWS ',$sql); 603 else 604 $sql = preg_replace('/^[ \t\n]*select/i','SELECT /*+FIRST_ROWS*/',$sql); 605 } 606 607 if ($offset == -1 || ($offset < $this->selectOffsetAlg1 && 0 < $nrows && $nrows < 1000)) { 608 if ($nrows > 0) { 609 if ($offset > 0) $nrows += $offset; 610 //$inputarr['adodb_rownum'] = $nrows; 611 if ($this->databaseType == 'oci8po') { 612 $sql = "select * from (".$sql.") where rownum <= ?"; 613 } else { 614 $sql = "select * from (".$sql.") where rownum <= :adodb_offset"; 615 } 616 $inputarr['adodb_offset'] = $nrows; 617 $nrows = -1; 618 } 619 // note that $nrows = 0 still has to work ==> no rows returned 620 621 $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache); 622 return $rs; 623 624 } else { 625 // Algorithm by Tomas V V Cox, from PEAR DB oci8.php 626 627 // Let Oracle return the name of the columns 628 $q_fields = "SELECT * FROM (".$sql.") WHERE NULL = NULL"; 629 630 $false = false; 631 if (! $stmt_arr = $this->Prepare($q_fields)) { 632 return $false; 633 } 634 $stmt = $stmt_arr[1]; 635 636 if (is_array($inputarr)) { 637 foreach($inputarr as $k => $v) { 638 if (is_array($v)) { 639 if (sizeof($v) == 2) // suggested by g.giunta@libero. 640 OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]); 641 else 642 OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]); 643 } else { 644 $len = -1; 645 if ($v === ' ') $len = 1; 646 if (isset($bindarr)) { // is prepared sql, so no need to ocibindbyname again 647 $bindarr[$k] = $v; 648 } else { // dynamic sql, so rebind every time 649 OCIBindByName($stmt,":$k",$inputarr[$k],$len); 650 651 } 652 } 653 } 654 } 655 656 if (!OCIExecute($stmt, OCI_DEFAULT)) { 657 OCIFreeStatement($stmt); 658 return $false; 659 } 660 661 $ncols = OCINumCols($stmt); 662 for ( $i = 1; $i <= $ncols; $i++ ) { 663 $cols[] = '"'.OCIColumnName($stmt, $i).'"'; 664 } 665 $result = false; 666 667 OCIFreeStatement($stmt); 668 $fields = implode(',', $cols); 669 if ($nrows <= 0) $nrows = 999999999999; 670 else $nrows += $offset; 671 $offset += 1; // in Oracle rownum starts at 1 672 673 if ($this->databaseType == 'oci8po') { 674 $sql = "SELECT /*+ FIRST_ROWS */ $fields FROM". 675 "(SELECT rownum as adodb_rownum, $fields FROM". 676 " ($sql) WHERE rownum <= ?". 677 ") WHERE adodb_rownum >= ?"; 678 } else { 679 $sql = "SELECT /*+ FIRST_ROWS */ $fields FROM". 680 "(SELECT rownum as adodb_rownum, $fields FROM". 681 " ($sql) WHERE rownum <= :adodb_nrows". 682 ") WHERE adodb_rownum >= :adodb_offset"; 683 } 684 $inputarr['adodb_nrows'] = $nrows; 685 $inputarr['adodb_offset'] = $offset; 686 687 if ($secs2cache>0) $rs = $this->CacheExecute($secs2cache, $sql,$inputarr); 688 else $rs = $this->Execute($sql,$inputarr); 689 return $rs; 690 } 691 692 } 693 694 /** 695 * Usage: 696 * Store BLOBs and CLOBs 697 * 698 * Example: to store $var in a blob 699 * 700 * $conn->Execute('insert into TABLE (id,ablob) values(12,empty_blob())'); 701 * $conn->UpdateBlob('TABLE', 'ablob', $varHoldingBlob, 'ID=12', 'BLOB'); 702 * 703 * $blobtype supports 'BLOB' and 'CLOB', but you need to change to 'empty_clob()'. 704 * 705 * to get length of LOB: 706 * select DBMS_LOB.GETLENGTH(ablob) from TABLE 707 * 708 * If you are using CURSOR_SHARING = force, it appears this will case a segfault 709 * under oracle 8.1.7.0. Run: 710 * $db->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT'); 711 * before UpdateBlob() then... 712 */ 713 714 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') 715 { 716 717 //if (strlen($val) < 4000) return $this->Execute("UPDATE $table SET $column=:blob WHERE $where",array('blob'=>$val)) != false; 718 719 switch(strtoupper($blobtype)) { 720 default: ADOConnection::outp("<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false; 721 case 'BLOB': $type = OCI_B_BLOB; break; 722 case 'CLOB': $type = OCI_B_CLOB; break; 723 } 724 725 if ($this->databaseType == 'oci8po') 726 $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?"; 727 else 728 $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob"; 729 730 $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB); 731 $arr['blob'] = array($desc,-1,$type); 732 if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT'); 733 $commit = $this->autoCommit; 734 if ($commit) $this->BeginTrans(); 735 $rs = $this->_Execute($sql,$arr); 736 if ($rez = !empty($rs)) $desc->save($val); 737 $desc->free(); 738 if ($commit) $this->CommitTrans(); 739 if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=FORCE'); 740 741 if ($rez) $rs->Close(); 742 return $rez; 743 } 744 745 /** 746 * Usage: store file pointed to by $val in a blob 747 */ 748 function UpdateBlobFile($table,$column,$val,$where,$blobtype='BLOB') 749 { 750 switch(strtoupper($blobtype)) { 751 default: ADOConnection::outp( "<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false; 752 case 'BLOB': $type = OCI_B_BLOB; break; 753 case 'CLOB': $type = OCI_B_CLOB; break; 754 } 755 756 if ($this->databaseType == 'oci8po') 757 $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?"; 758 else 759 $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob"; 760 761 $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB); 762 $arr['blob'] = array($desc,-1,$type); 763 764 $this->BeginTrans(); 765 $rs = ADODB_oci8::Execute($sql,$arr); 766 if ($rez = !empty($rs)) $desc->savefile($val); 767 $desc->free(); 768 $this->CommitTrans(); 769 770 if ($rez) $rs->Close(); 771 return $rez; 772 } 773 774 /** 775 * Execute SQL 776 * 777 * @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text) 778 * @param [inputarr] holds the input data to bind to. Null elements will be set to null. 779 * @return RecordSet or false 780 */ 781 function Execute($sql,$inputarr=false) 782 { 783 if ($this->fnExecute) { 784 $fn = $this->fnExecute; 785 $ret = $fn($this,$sql,$inputarr); 786 if (isset($ret)) return $ret; 787 } 788 if ($inputarr) { 789 #if (!is_array($inputarr)) $inputarr = array($inputarr); 790 791 $element0 = reset($inputarr); 792 793 if (!$this->_bindInputArray) { 794 # is_object check because oci8 descriptors can be passed in 795 if (is_array($element0) && !is_object(reset($element0))) { 796 if (is_string($sql)) 797 $stmt = $this->Prepare($sql); 798 else 799 $stmt = $sql; 800 801 foreach($inputarr as $arr) { 802 $ret = $this->_Execute($stmt,$arr); 803 if (!$ret) return $ret; 804 } 805 } else { 806 $sqlarr = explode(':',$sql); 807 $sql = ''; 808 $lastnomatch = -2; 809 #var_dump($sqlarr);echo "<hr>";var_dump($inputarr);echo"<hr>"; 810 foreach($sqlarr as $k => $str) { 811 if ($k == 0) { $sql = $str; continue; } 812 // we need $lastnomatch because of the following datetime, 813 // eg. '10:10:01', which causes code to think that there is bind param :10 and :1 814 $ok = preg_match('/^([0-9]*)/', $str, $arr); 815 816 if (!$ok) $sql .= $str; 817 else { 818 $at = $arr[1]; 819 if (isset($inputarr[$at]) || is_null($inputarr[$at])) { 820 if ((strlen($at) == strlen($str) && $k < sizeof($arr)-1)) { 821 $sql .= ':'.$str; 822 $lastnomatch = $k; 823 } else if ($lastnomatch == $k-1) { 824 $sql .= ':'.$str; 825 } else { 826 if (is_null($inputarr[$at])) $sql .= 'null'; 827 else $sql .= $this->qstr($inputarr[$at]); 828 $sql .= substr($str, strlen($at)); 829 } 830 } else { 831 $sql .= ':'.$str; 832 } 833 834 } 835 } 836 $inputarr = false; 837 } 838 } 839 $ret = $this->_Execute($sql,$inputarr); 840 841 842 } else { 843 $ret = $this->_Execute($sql,false); 844 } 845 846 return $ret; 847 } 848 849 /* 850 Example of usage: 851 852 $stmt = $this->Prepare('insert into emp (empno, ename) values (:empno, :ename)'); 853 */ 854 function Prepare($sql,$cursor=false) 855 { 856 static $BINDNUM = 0; 857 858 $stmt = OCIParse($this->_connectionID,$sql); 859 860 if (!$stmt) { 861 $this->_errorMsg = false; 862 $this->_errorCode = false; 863 $arr = @OCIError($this->_connectionID); 864 if ($arr === false) return false; 865 866 $this->_errorMsg = $arr['message']; 867 $this->_errorCode = $arr['code']; 868 return false; 869 } 870 871 $BINDNUM += 1; 872 873 $sttype = @OCIStatementType($stmt); 874 if ($sttype == 'BEGIN' || $sttype == 'DECLARE') { 875 return array($sql,$stmt,0,$BINDNUM, ($cursor) ? OCINewCursor($this->_connectionID) : false); 876 } 877 return array($sql,$stmt,0,$BINDNUM); 878 } 879 880 /* 881 Call an oracle stored procedure and returns a cursor variable as a recordset. 882 Concept by Robert Tuttle robert@ud.com 883 884 Example: 885 Note: we return a cursor variable in :RS2 886 $rs = $db->ExecuteCursor("BEGIN adodb.open_tab(:RS2); END;",'RS2'); 887 888 $rs = $db->ExecuteCursor( 889 "BEGIN :RS2 = adodb.getdata(:VAR1); END;", 890 'RS2', 891 array('VAR1' => 'Mr Bean')); 892 893 */ 894 function ExecuteCursor($sql,$cursorName='rs',$params=false) 895 { 896 if (is_array($sql)) $stmt = $sql; 897 else $stmt = ADODB_oci8::Prepare($sql,true); # true to allocate OCINewCursor 898 899 if (is_array($stmt) && sizeof($stmt) >= 5) { 900 $hasref = true; 901 $ignoreCur = false; 902 $this->Parameter($stmt, $ignoreCur, $cursorName, false, -1, OCI_B_CURSOR); 903 if ($params) { 904 foreach($params as $k => $v) { 905 $this->Parameter($stmt,$params[$k], $k); 906 } 907 } 908 } else 909 $hasref = false; 910 911 $rs = $this->Execute($stmt); 912 if ($rs) { 913 if ($rs->databaseType == 'array') OCIFreeCursor($stmt[4]); 914 else if ($hasref) $rs->_refcursor = $stmt[4]; 915 } 916 return $rs; 917 } 918 919 /* 920 Bind a variable -- very, very fast for executing repeated statements in oracle. 921 Better than using 922 for ($i = 0; $i < $max; $i++) { 923 $p1 = ?; $p2 = ?; $p3 = ?; 924 $this->Execute("insert into table (col0, col1, col2) values (:0, :1, :2)", 925 array($p1,$p2,$p3)); 926 } 927 928 Usage: 929 $stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)"); 930 $DB->Bind($stmt, $p1); 931 $DB->Bind($stmt, $p2); 932 $DB->Bind($stmt, $p3); 933 for ($i = 0; $i < $max; $i++) { 934 $p1 = ?; $p2 = ?; $p3 = ?; 935 $DB->Execute($stmt); 936 } 937 938 Some timings: 939 ** Test table has 3 cols, and 1 index. Test to insert 1000 records 940 Time 0.6081s (1644.60 inserts/sec) with direct OCIParse/OCIExecute 941 Time 0.6341s (1577.16 inserts/sec) with ADOdb Prepare/Bind/Execute 942 Time 1.5533s ( 643.77 inserts/sec) with pure SQL using Execute 943 944 Now if PHP only had batch/bulk updating like Java or PL/SQL... 945 946 Note that the order of parameters differs from OCIBindByName, 947 because we default the names to :0, :1, :2 948 */ 949 function Bind(&$stmt,&$var,$size=4000,$type=false,$name=false,$isOutput=false) 950 { 951 952 if (!is_array($stmt)) return false; 953 954 if (($type == OCI_B_CURSOR) && sizeof($stmt) >= 5) { 955 return OCIBindByName($stmt[1],":".$name,$stmt[4],$size,$type); 956 } 957 958 if ($name == false) { 959 if ($type !== false) $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size,$type); 960 else $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size); // +1 byte for null terminator 961 $stmt[2] += 1; 962 } else if (oci_lob_desc($type)) { 963 if ($this->debug) { 964 ADOConnection::outp("<b>Bind</b>: name = $name"); 965 } 966 //we have to create a new Descriptor here 967 $numlob = count($this->_refLOBs); 968 $this->_refLOBs[$numlob]['LOB'] = OCINewDescriptor($this->_connectionID, oci_lob_desc($type)); 969 $this->_refLOBs[$numlob]['TYPE'] = $isOutput; 970 971 $tmp = $this->_refLOBs[$numlob]['LOB']; 972 $rez = OCIBindByName($stmt[1], ":".$name, $tmp, -1, $type); 973 if ($this->debug) { 974 ADOConnection::outp("<b>Bind</b>: descriptor has been allocated, var (".$name.") binded"); 975 } 976 977 // if type is input then write data to lob now 978 if ($isOutput == false) { 979 $var = $this->BlobEncode($var); 980 $tmp->WriteTemporary($var); 981 $this->_refLOBs[$numlob]['VAR'] = &$var; 982 if ($this->debug) { 983 ADOConnection::outp("<b>Bind</b>: LOB has been written to temp"); 984 } 985 } else { 986 $this->_refLOBs[$numlob]['VAR'] = &$var; 987 } 988 $rez = $tmp; 989 } else { 990 if ($this->debug) 991 ADOConnection::outp("<b>Bind</b>: name = $name"); 992 993 if ($type !== false) $rez = OCIBindByName($stmt[1],":".$name,$var,$size,$type); 994 else $rez = OCIBindByName($stmt[1],":".$name,$var,$size); // +1 byte for null terminator 995 } 996 997 return $rez; 998 } 999 1000 function Param($name,$type=false) 1001 { 1002 return ':'.$name; 1003 } 1004 1005 /* 1006 Usage: 1007 $stmt = $db->Prepare('select * from table where id =:myid and group=:group'); 1008 $db->Parameter($stmt,$id,'myid'); 1009 $db->Parameter($stmt,$group,'group'); 1010 $db->Execute($stmt); 1011 1012 @param $stmt Statement returned by Prepare() or PrepareSP(). 1013 @param $var PHP variable to bind to 1014 @param $name Name of stored procedure variable name to bind to. 1015 @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8. 1016 @param [$maxLen] Holds an maximum length of the variable. 1017 @param [$type] The data type of $var. Legal values depend on driver. 1018 1019 See OCIBindByName documentation at php.net. 1020 */ 1021 function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false) 1022 { 1023 if ($this->debug) { 1024 $prefix = ($isOutput) ? 'Out' : 'In'; 1025 $ztype = (empty($type)) ? 'false' : $type; 1026 ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);"); 1027 } 1028 return $this->Bind($stmt,$var,$maxLen,$type,$name,$isOutput); 1029 } 1030 1031 /* 1032 returns query ID if successful, otherwise false 1033 this version supports: 1034 1035 1. $db->execute('select * from table'); 1036 1037 2. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)'); 1038 $db->execute($prepared_statement, array(1,2,3)); 1039 1040 3. $db->execute('insert into table (a,b,c) values (:a,:b,:c)',array('a'=>1,'b'=>2,'c'=>3)); 1041 1042 4. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)'); 1043 $db->bind($stmt,1); $db->bind($stmt,2); $db->bind($stmt,3); 1044 $db->execute($stmt); 1045 */ 1046 function _query($sql,$inputarr=false) 1047 { 1048 if (is_array($sql)) { // is prepared sql 1049 $stmt = $sql[1]; 1050 1051 // we try to bind to permanent array, so that OCIBindByName is persistent 1052 // and carried out once only - note that max array element size is 4000 chars 1053 if (is_array($inputarr)) { 1054 $bindpos = $sql[3]; 1055 if (isset($this->_bind[$bindpos])) { 1056 // all tied up already 1057 $bindarr = $this->_bind[$bindpos]; 1058 } else { 1059 // one statement to bind them all 1060 $bindarr = array(); 1061 foreach($inputarr as $k => $v) { 1062 $bindarr[$k] = $v; 1063 OCIBindByName($stmt,":$k",$bindarr[$k],is_string($v) && strlen($v)>4000 ? -1 : 4000); 1064 } 1065 $this->_bind[$bindpos] = $bindarr; 1066 } 1067 } 1068 } else { 1069 $stmt=OCIParse($this->_connectionID,$sql); 1070 } 1071 1072 $this->_stmt = $stmt; 1073 if (!$stmt) return false; 1074 1075 if (defined('ADODB_PREFETCH_ROWS')) @OCISetPrefetch($stmt,ADODB_PREFETCH_ROWS); 1076 1077 if (is_array($inputarr)) { 1078 foreach($inputarr as $k => $v) { 1079 if (is_array($v)) { 1080 if (sizeof($v) == 2) // suggested by g.giunta@libero. 1081 OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]); 1082 else 1083 OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]); 1084 1085 if ($this->debug==99) { 1086 if (is_object($v[0])) 1087 echo "name=:$k",' len='.$v[1],' type='.$v[2],'<br>'; 1088 else 1089 echo "name=:$k",' var='.$inputarr[$k][0],' len='.$v[1],' type='.$v[2],'<br>'; 1090 1091 } 1092 } else { 1093 $len = -1; 1094 if ($v === ' ') $len = 1; 1095 if (isset($bindarr)) { // is prepared sql, so no need to ocibindbyname again 1096 $bindarr[$k] = $v; 1097 } else { // dynamic sql, so rebind every time 1098 OCIBindByName($stmt,":$k",$inputarr[$k],$len); 1099 } 1100 } 1101 } 1102 } 1103 1104 $this->_errorMsg = false; 1105 $this->_errorCode = false; 1106 if (OCIExecute($stmt,$this->_commit)) { 1107 //OCIInternalDebug(1); 1108 if (count($this -> _refLOBs) > 0) { 1109 1110 foreach ($this -> _refLOBs as $key => $value) { 1111 if ($this -> _refLOBs[$key]['TYPE'] == true) { 1112 $tmp = $this -> _refLOBs[$key]['LOB'] -> load(); 1113 if ($this -> debug) { 1114 ADOConnection::outp("<b>OUT LOB</b>: LOB has been loaded. <br>"); 1115 } 1116 //$_GLOBALS[$this -> _refLOBs[$key]['VAR']] = $tmp; 1117 $this -> _refLOBs[$key]['VAR'] = $tmp; 1118 } else { 1119 $this->_refLOBs[$key]['LOB']->save($this->_refLOBs[$key]['VAR']); 1120 $this -> _refLOBs[$key]['LOB']->free(); 1121 unset($this -> _refLOBs[$key]); 1122 if ($this->debug) { 1123 ADOConnection::outp("<b>IN LOB</b>: LOB has been saved. <br>"); 1124 } 1125 } 1126 } 1127 } 1128 1129 switch (@OCIStatementType($stmt)) { 1130 case "SELECT": 1131 return $stmt; 1132 1133 case 'DECLARE': 1134 case "BEGIN": 1135 if (is_array($sql) && !empty($sql[4])) { 1136 $cursor = $sql[4]; 1137 if (is_resource($cursor)) { 1138 $ok = OCIExecute($cursor); 1139 return $cursor; 1140 } 1141 return $stmt; 1142 } else { 1143 if (is_resource($stmt)) { 1144 OCIFreeStatement($stmt); 1145 return true; 1146 } 1147 return $stmt; 1148 } 1149 break; 1150 default : 1151 // ociclose -- no because it could be used in a LOB? 1152 return true; 1153 } 1154 } 1155 return false; 1156 } 1157 1158 // From Oracle Whitepaper: PHP Scalability and High Availability 1159 function IsConnectionError($err) 1160 { 1161 switch($err) { 1162 case 378: /* buffer pool param incorrect */ 1163 case 602: /* core dump */ 1164 case 603: /* fatal error */ 1165 case 609: /* attach failed */ 1166 case 1012: /* not logged in */ 1167 case 1033: /* init or shutdown in progress */ 1168 case 1043: /* Oracle not available */ 1169 case 1089: /* immediate shutdown in progress */ 1170 case 1090: /* shutdown in progress */ 1171 case 1092: /* instance terminated */ 1172 case 3113: /* disconnect */ 1173 case 3114: /* not connected */ 1174 case 3122: /* closing window */ 1175 case 3135: /* lost contact */ 1176 case 12153: /* TNS: not connected */ 1177 case 27146: /* fatal or instance terminated */ 1178 case 28511: /* Lost RPC */ 1179 return true; 1180 } 1181 return false; 1182 } 1183 1184 // returns true or false 1185 function _close() 1186 { 1187 if (!$this->_connectionID) return; 1188 1189 if (!$this->autoCommit) OCIRollback($this->_connectionID); 1190 if (count($this->_refLOBs) > 0) { 1191 foreach ($this ->_refLOBs as $key => $value) { 1192 $this->_refLOBs[$key]['LOB']->free(); 1193 unset($this->_refLOBs[$key]); 1194 } 1195 } 1196 OCILogoff($this->_connectionID); 1197 1198 $this->_stmt = false; 1199 $this->_connectionID = false; 1200 } 1201 1202 function MetaPrimaryKeys($table, $owner=false,$internalKey=false) 1203 { 1204 if ($internalKey) return array('ROWID'); 1205 1206 // tested with oracle 8.1.7 1207 $table = strtoupper($table); 1208 if ($owner) { 1209 $owner_clause = "AND ((a.OWNER = b.OWNER) AND (a.OWNER = UPPER('$owner')))"; 1210 $ptab = 'ALL_'; 1211 } else { 1212 $owner_clause = ''; 1213 $ptab = 'USER_'; 1214 } 1215 $sql = " 1216 SELECT /*+ RULE */ distinct b.column_name 1217 FROM {$ptab}CONSTRAINTS a 1218 , {$ptab}CONS_COLUMNS b 1219 WHERE ( UPPER(b.table_name) = ('$table')) 1220 AND (UPPER(a.table_name) = ('$table') and a.constraint_type = 'P') 1221 $owner_clause 1222 AND (a.constraint_name = b.constraint_name)"; 1223 1224 $rs = $this->Execute($sql); 1225 if ($rs && !$rs->EOF) { 1226 $arr = $rs->GetArray(); 1227 $a = array(); 1228 foreach($arr as $v) { 1229 $a[] = reset($v); 1230 } 1231 return $a; 1232 } 1233 else return false; 1234 } 1235 1236 // http://gis.mit.edu/classes/11.521/sqlnotes/referential_integrity.html 1237 function MetaForeignKeys($table, $owner=false) 1238 { 1239 global $ADODB_FETCH_MODE; 1240 1241 $save = $ADODB_FETCH_MODE; 1242 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 1243 $table = $this->qstr(strtoupper($table)); 1244 if (!$owner) { 1245 $owner = $this->user; 1246 $tabp = 'user_'; 1247 } else 1248 $tabp = 'all_'; 1249 1250 $owner = ' and owner='.$this->qstr(strtoupper($owner)); 1251 1252 $sql = 1253 "select constraint_name,r_owner,r_constraint_name 1254 from {$tabp}constraints 1255 where constraint_type = 'R' and table_name = $table $owner"; 1256 1257 $constraints = $this->GetArray($sql); 1258 $arr = false; 1259 foreach($constraints as $constr) { 1260 $cons = $this->qstr($constr[0]); 1261 $rowner = $this->qstr($constr[1]); 1262 $rcons = $this->qstr($constr[2]); 1263 $cols = $this->GetArray("select column_name from {$tabp}cons_columns where constraint_name=$cons $owner order by position"); 1264 $tabcol = $this->GetArray("select table_name,column_name from {$tabp}cons_columns where owner=$rowner and constraint_name=$rcons order by position"); 1265 1266 if ($cols && $tabcol) 1267 for ($i=0, $max=sizeof($cols); $i < $max; $i++) { 1268 $arr[$tabcol[$i][0]] = $cols[$i][0].'='.$tabcol[$i][1]; 1269 } 1270 } 1271 $ADODB_FETCH_MODE = $save; 1272 1273 return $arr; 1274 } 1275 1276 1277 function CharMax() 1278 { 1279 return 4000; 1280 } 1281 1282 function TextMax() 1283 { 1284 return 4000; 1285 } 1286 1287 /** 1288 * Quotes a string. 1289 * An example is $db->qstr("Don't bother",magic_quotes_runtime()); 1290 * 1291 * @param s the string to quote 1292 * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc(). 1293 * This undoes the stupidity of magic quotes for GPC. 1294 * 1295 * @return quoted string to be sent back to database 1296 */ 1297 function qstr($s,$magic_quotes=false) 1298 { 1299 //$nofixquotes=false; 1300 1301 if ($this->noNullStrings && strlen($s)==0)$s = ' '; 1302 if (!$magic_quotes) { 1303 if ($this->replaceQuote[0] == '\\'){ 1304 $s = str_replace('\\','\\\\',$s); 1305 } 1306 return "'".str_replace("'",$this->replaceQuote,$s)."'"; 1307 } 1308 1309 // undo magic quotes for " unless sybase is on 1310 if (!ini_get('magic_quotes_sybase')) { 1311 $s = str_replace('\\"','"',$s); 1312 $s = str_replace('\\\\','\\',$s); 1313 return "'".str_replace("\\'",$this->replaceQuote,$s)."'"; 1314 } else { 1315 return "'".$s."'"; 1316 } 1317 } 1318 1319 } 1320 1321 /*-------------------------------------------------------------------------------------- 1322 Class Name: Recordset 1323 --------------------------------------------------------------------------------------*/ 1324 1325 class ADORecordset_oci8 extends ADORecordSet { 1326 1327 var $databaseType = 'oci8'; 1328 var $bind=false; 1329 var $_fieldobjs; 1330 1331 //var $_arr = false; 1332 1333 function ADORecordset_oci8($queryID,$mode=false) 1334 { 1335 if ($mode === false) { 1336 global $ADODB_FETCH_MODE; 1337 $mode = $ADODB_FETCH_MODE; 1338 } 1339 switch ($mode) 1340 { 1341 case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; 1342 case ADODB_FETCH_DEFAULT: 1343 case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; 1344 case ADODB_FETCH_NUM: 1345 default: 1346 $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; 1347 } 1348 1349 $this->adodbFetchMode = $mode; 1350 $this->_queryID = $queryID; 1351 } 1352 1353 1354 function Init() 1355 { 1356 if ($this->_inited) return; 1357 1358 $this->_inited = true; 1359 if ($this->_queryID) { 1360 1361 $this->_currentRow = 0; 1362 @$this->_initrs(); 1363 $this->EOF = !$this->_fetch(); 1364 1365 /* 1366 // based on idea by Gaetano Giunta to detect unusual oracle errors 1367 // see http://phplens.com/lens/lensforum/msgs.php?id=6771 1368 $err = OCIError($this->_queryID); 1369 if ($err && $this->connection->debug) ADOConnection::outp($err); 1370 */ 1371 1372 if (!is_array($this->fields)) { 1373 $this->_numOfRows = 0; 1374 $this->fields = array(); 1375 } 1376 } else { 1377 $this->fields = array(); 1378 $this->_numOfRows = 0; 1379 $this->_numOfFields = 0; 1380 $this->EOF = true; 1381 } 1382 } 1383 1384 function _initrs() 1385 { 1386 $this->_numOfRows = -1; 1387 $this->_numOfFields = OCInumcols($this->_queryID); 1388 if ($this->_numOfFields>0) { 1389 $this->_fieldobjs = array(); 1390 $max = $this->_numOfFields; 1391 for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i); 1392 } 1393 } 1394 1395 /* Returns: an object containing field information. 1396 Get column information in the Recordset object. fetchField() can be used in order to obtain information about 1397 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by 1398 fetchField() is retrieved. */ 1399 1400 function _FetchField($fieldOffset = -1) 1401 { 1402 $fld = new ADOFieldObject; 1403 $fieldOffset += 1; 1404 $fld->name =OCIcolumnname($this->_queryID, $fieldOffset); 1405 $fld->type = OCIcolumntype($this->_queryID, $fieldOffset); 1406 $fld->max_length = OCIcolumnsize($this->_queryID, $fieldOffset); 1407 switch($fld->type) { 1408 case 'NUMBER': 1409 $p = OCIColumnPrecision($this->_queryID, $fieldOffset); 1410 $sc = OCIColumnScale($this->_queryID, $fieldOffset); 1411 if ($p != 0 && $sc == 0) $fld->type = 'INT'; 1412 $fld->scale = $p; 1413 break; 1414 1415 case 'CLOB': 1416 case 'NCLOB': 1417 case 'BLOB': 1418 $fld->max_length = -1; 1419 break; 1420 } 1421 return $fld; 1422 } 1423 1424 /* For some reason, OCIcolumnname fails when called after _initrs() so we cache it */ 1425 function FetchField($fieldOffset = -1) 1426 { 1427 return $this->_fieldobjs[$fieldOffset]; 1428 } 1429 1430 1431 /* 1432 // 10% speedup to move MoveNext to child class 1433 function _MoveNext() 1434 { 1435 //global $ADODB_EXTENSION;if ($ADODB_EXTENSION) return @adodb_movenext($this); 1436 1437 if ($this->EOF) return false; 1438 1439 $this->_currentRow++; 1440 if(@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) 1441 return true; 1442 $this->EOF = true; 1443 1444 return false; 1445 } */ 1446 1447 1448 function MoveNext() 1449 { 1450 if (@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) { 1451 $this->_currentRow += 1; 1452 return true; 1453 } 1454 if (!$this->EOF) { 1455 $this->_currentRow += 1; 1456 $this->EOF = true; 1457 } 1458 return false; 1459 } 1460 1461 /* 1462 # does not work as first record is retrieved in _initrs(), so is not included in GetArray() 1463 function GetArray($nRows = -1) 1464 { 1465 global $ADODB_OCI8_GETARRAY; 1466 1467 if (true || !empty($ADODB_OCI8_GETARRAY)) { 1468 # does not support $ADODB_ANSI_PADDING_OFF 1469 1470 //OCI_RETURN_NULLS and OCI_RETURN_LOBS is set by OCIfetchstatement 1471 switch($this->adodbFetchMode) { 1472 case ADODB_FETCH_NUM: 1473 1474 $ncols = @OCIfetchstatement($this->_queryID, $results, 0, $nRows, OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM); 1475 $results = array_merge(array($this->fields),$results); 1476 return $results; 1477 1478 case ADODB_FETCH_ASSOC: 1479 if (ADODB_ASSOC_CASE != 2 || $this->databaseType != 'oci8') break; 1480 1481 $ncols = @OCIfetchstatement($this->_queryID, $assoc, 0, $nRows, OCI_FETCHSTATEMENT_BY_ROW); 1482 $results = array_merge(array($this->fields),$assoc); 1483 return $results; 1484 1485 default: 1486 break; 1487 } 1488 } 1489 1490 $results = ADORecordSet::GetArray($nRows); 1491 return $results; 1492 1493 } */ 1494 1495 /* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */ 1496 function GetArrayLimit($nrows,$offset=-1) 1497 { 1498 if ($offset <= 0) { 1499 $arr = $this->GetArray($nrows); 1500 return $arr; 1501 } 1502 $arr = array(); 1503 for ($i=1; $i < $offset; $i++) 1504 if (!@OCIFetch($this->_queryID)) return $arr; 1505 1506 if (!@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) return $arr;; 1507 $results = array(); 1508 $cnt = 0; 1509 while (!$this->EOF && $nrows != $cnt) { 1510 $results[$cnt++] = $this->fields; 1511 $this->MoveNext(); 1512 } 1513 1514 return $results; 1515 } 1516 1517 1518 /* Use associative array to get fields array */ 1519 function Fields($colname) 1520 { 1521 if (!$this->bind) { 1522 $this->bind = array(); 1523 for ($i=0; $i < $this->_numOfFields; $i++) { 1524 $o = $this->FetchField($i); 1525 $this->bind[strtoupper($o->name)] = $i; 1526 } 1527 } 1528 1529 return $this->fields[$this->bind[strtoupper($colname)]]; 1530 } 1531 1532 1533 1534 function _seek($row) 1535 { 1536 return false; 1537 } 1538 1539 function _fetch() 1540 { 1541 return @OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode); 1542 } 1543 1544 /* close() only needs to be called if you are worried about using too much memory while your script 1545 is running. All associated result memory for the specified result identifier will automatically be freed. */ 1546 1547 function _close() 1548 { 1549 if ($this->connection->_stmt === $this->_queryID) $this->connection->_stmt = false; 1550 if (!empty($this->_refcursor)) { 1551 OCIFreeCursor($this->_refcursor); 1552 $this->_refcursor = false; 1553 } 1554 @OCIFreeStatement($this->_queryID); 1555 $this->_queryID = false; 1556 1557 } 1558 1559 function MetaType($t,$len=-1) 1560 { 1561 if (is_object($t)) { 1562 $fieldobj = $t; 1563 $t = $fieldobj->type; 1564 $len = $fieldobj->max_length; 1565 } 1566 switch (strtoupper($t)) { 1567 case 'VARCHAR': 1568 case 'VARCHAR2': 1569 case 'CHAR': 1570 case 'VARBINARY': 1571 case 'BINARY': 1572 case 'NCHAR': 1573 case 'NVARCHAR': 1574 case 'NVARCHAR2': 1575 if ($len <= $this->blobSize) return 'C'; 1576 1577 case 'NCLOB': 1578 case 'LONG': 1579 case 'LONG VARCHAR': 1580 case 'CLOB': 1581 return 'X'; 1582 1583 case 'LONG RAW': 1584 case 'LONG VARBINARY': 1585 case 'BLOB': 1586 return 'B'; 1587 1588 case 'DATE': 1589 return ($this->connection->datetime) ? 'T' : 'D'; 1590 1591 1592 case 'TIMESTAMP': return 'T'; 1593 1594 case 'INT': 1595 case 'SMALLINT': 1596 case 'INTEGER': 1597 return 'I'; 1598 1599 default: return 'N'; 1600 } 1601 } 1602 } 1603 1604 class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 { 1605 function ADORecordSet_ext_oci8($queryID,$mode=false) 1606 { 1607 if ($mode === false) { 1608 global $ADODB_FETCH_MODE; 1609 $mode = $ADODB_FETCH_MODE; 1610 } 1611 switch ($mode) 1612 { 1613 case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; 1614 case ADODB_FETCH_DEFAULT: 1615 case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; 1616 case ADODB_FETCH_NUM: 1617 default: $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; 1618 } 1619 $this->adodbFetchMode = $mode; 1620 $this->_queryID = $queryID; 1621 } 1622 1623 function MoveNext() 1624 { 1625 return adodb_movenext($this); 1626 } 1627 } 1628 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |