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