[ Index ] |
|
Code source de SPIP Agora 1.4 |
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ 3 // +----------------------------------------------------------------------+ 4 // | PHP Version 4 | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1997-2004 The PHP Group | 7 // +----------------------------------------------------------------------+ 8 // | This source file is subject to version 2.02 of the PHP license, | 9 // | that is bundled with this package in the file LICENSE, and is | 10 // | available at through the world-wide-web at | 11 // | http://www.php.net/license/2_02.txt. | 12 // | If you did not receive a copy of the PHP license and are unable to | 13 // | obtain it through the world-wide-web, please send a note to | 14 // | license@php.net so we can mail you a copy immediately. | 15 // +----------------------------------------------------------------------+ 16 // | Author: James L. Pine <jlp@valinux.com> | 17 // | Maintainer: Daniel Convissor <danielc@php.net> | 18 // +----------------------------------------------------------------------+ 19 // 20 // $Id: oci8.php,v 1.67 2004/06/24 15:24:56 danielc Exp $ 21 22 23 // be aware... OCIError() only appears to return anything when given a 24 // statement, so functions return the generic DB_ERROR instead of more 25 // useful errors that have to do with feedback from the database. 26 27 28 require_once 'DB/common.php'; 29 30 /** 31 * Database independent query interface definition for PHP's Oracle 8 32 * call-interface extension. 33 * 34 * Definitely works with versions 8 and 9 of Oracle. 35 * 36 * @package DB 37 * @version $Id: oci8.php,v 1.67 2004/06/24 15:24:56 danielc Exp $ 38 * @category Database 39 * @author James L. Pine <jlp@valinux.com> 40 */ 41 class DB_oci8 extends DB_common 42 { 43 // {{{ properties 44 45 var $connection; 46 var $phptype, $dbsyntax; 47 var $manip_query = array(); 48 var $prepare_types = array(); 49 var $autoCommit = 1; 50 var $last_stmt = false; 51 52 /** 53 * stores the $data passed to execute() in the oci8 driver 54 * 55 * Gets reset to array() when simpleQuery() is run. 56 * 57 * Needed in case user wants to call numRows() after prepare/execute 58 * was used. 59 * 60 * @var array 61 * @access private 62 */ 63 var $_data = array(); 64 65 // }}} 66 // {{{ constructor 67 68 function DB_oci8() 69 { 70 $this->DB_common(); 71 $this->phptype = 'oci8'; 72 $this->dbsyntax = 'oci8'; 73 $this->features = array( 74 'prepare' => false, 75 'pconnect' => true, 76 'transactions' => true, 77 'limit' => 'alter' 78 ); 79 $this->errorcode_map = array( 80 1 => DB_ERROR_CONSTRAINT, 81 900 => DB_ERROR_SYNTAX, 82 904 => DB_ERROR_NOSUCHFIELD, 83 921 => DB_ERROR_SYNTAX, 84 923 => DB_ERROR_SYNTAX, 85 942 => DB_ERROR_NOSUCHTABLE, 86 955 => DB_ERROR_ALREADY_EXISTS, 87 1400 => DB_ERROR_CONSTRAINT_NOT_NULL, 88 1407 => DB_ERROR_CONSTRAINT_NOT_NULL, 89 1476 => DB_ERROR_DIVZERO, 90 1722 => DB_ERROR_INVALID_NUMBER, 91 2289 => DB_ERROR_NOSUCHTABLE, 92 2291 => DB_ERROR_CONSTRAINT, 93 2292 => DB_ERROR_CONSTRAINT, 94 2449 => DB_ERROR_CONSTRAINT, 95 ); 96 } 97 98 // }}} 99 // {{{ connect() 100 101 /** 102 * Connect to a database and log in as the specified user. 103 * 104 * @param $dsn the data source name (see DB::parseDSN for syntax) 105 * @param $persistent (optional) whether the connection should 106 * be persistent 107 * 108 * @return int DB_OK on success, a DB error code on failure 109 */ 110 function connect($dsninfo, $persistent = false) 111 { 112 if (!DB::assertExtension('oci8')) { 113 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 114 } 115 $this->dsn = $dsninfo; 116 117 $connect_function = $persistent ? 'OCIPLogon' : 'OCILogon'; 118 119 if ($dsninfo['hostspec']) { 120 $conn = @$connect_function($dsninfo['username'], 121 $dsninfo['password'], 122 $dsninfo['hostspec']); 123 } elseif ($dsninfo['username'] || $dsninfo['password']) { 124 $conn = @$connect_function($dsninfo['username'], 125 $dsninfo['password']); 126 } else { 127 $conn = false; 128 } 129 if ($conn == false) { 130 $error = OCIError(); 131 $error = (is_array($error)) ? $error['message'] : null; 132 return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null, 133 null, $error); 134 } 135 $this->connection = $conn; 136 return DB_OK; 137 } 138 139 // }}} 140 // {{{ disconnect() 141 142 /** 143 * Log out and disconnect from the database. 144 * 145 * @return bool true on success, false if not connected. 146 */ 147 function disconnect() 148 { 149 $ret = @OCILogOff($this->connection); 150 $this->connection = null; 151 return $ret; 152 } 153 154 // }}} 155 // {{{ simpleQuery() 156 157 /** 158 * Send a query to oracle and return the results as an oci8 resource 159 * identifier. 160 * 161 * @param $query the SQL query 162 * 163 * @return int returns a valid oci8 result for successful SELECT 164 * queries, DB_OK for other successful queries. A DB error code 165 * is returned on failure. 166 */ 167 function simpleQuery($query) 168 { 169 $this->_data = array(); 170 $this->last_query = $query; 171 $query = $this->modifyQuery($query); 172 $result = @OCIParse($this->connection, $query); 173 if (!$result) { 174 return $this->oci8RaiseError(); 175 } 176 if ($this->autoCommit) { 177 $success = @OCIExecute($result,OCI_COMMIT_ON_SUCCESS); 178 } else { 179 $success = @OCIExecute($result,OCI_DEFAULT); 180 } 181 if (!$success) { 182 return $this->oci8RaiseError($result); 183 } 184 $this->last_stmt=$result; 185 // Determine which queries that should return data, and which 186 // should return an error code only. 187 return DB::isManip($query) ? DB_OK : $result; 188 } 189 190 // }}} 191 // {{{ nextResult() 192 193 /** 194 * Move the internal oracle result pointer to the next available result 195 * 196 * @param a valid oci8 result resource 197 * 198 * @access public 199 * 200 * @return true if a result is available otherwise return false 201 */ 202 function nextResult($result) 203 { 204 return false; 205 } 206 207 // }}} 208 // {{{ fetchInto() 209 210 /** 211 * Fetch a row and insert the data into an existing array. 212 * 213 * Formating of the array and the data therein are configurable. 214 * See DB_result::fetchInto() for more information. 215 * 216 * @param resource $result query result identifier 217 * @param array $arr (reference) array where data from the row 218 * should be placed 219 * @param int $fetchmode how the resulting array should be indexed 220 * @param int $rownum the row number to fetch 221 * 222 * @return mixed DB_OK on success, null when end of result set is 223 * reached or on failure 224 * 225 * @see DB_result::fetchInto() 226 * @access private 227 */ 228 function fetchInto($result, &$arr, $fetchmode, $rownum=null) 229 { 230 if ($rownum !== null) { 231 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 232 } 233 if ($fetchmode & DB_FETCHMODE_ASSOC) { 234 $moredata = @OCIFetchInto($result,$arr,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS); 235 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && 236 $moredata) 237 { 238 $arr = array_change_key_case($arr, CASE_LOWER); 239 } 240 } else { 241 $moredata = OCIFetchInto($result,$arr,OCI_RETURN_NULLS+OCI_RETURN_LOBS); 242 } 243 if (!$moredata) { 244 return null; 245 } 246 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 247 $this->_rtrimArrayValues($arr); 248 } 249 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 250 $this->_convertNullArrayValuesToEmpty($arr); 251 } 252 return DB_OK; 253 } 254 255 // }}} 256 // {{{ freeResult() 257 258 /** 259 * Free the internal resources associated with $result. 260 * 261 * @param $result oci8 result identifier 262 * 263 * @return bool true on success, false if $result is invalid 264 */ 265 function freeResult($result) 266 { 267 return @OCIFreeStatement($result); 268 } 269 270 /** 271 * Free the internal resources associated with a prepared query. 272 * 273 * @param $stmt oci8 statement identifier 274 * 275 * @return bool true on success, false if $result is invalid 276 */ 277 function freePrepared($stmt) 278 { 279 if (isset($this->prepare_types[(int)$stmt])) { 280 unset($this->prepare_types[(int)$stmt]); 281 unset($this->manip_query[(int)$stmt]); 282 } else { 283 return false; 284 } 285 return true; 286 } 287 288 // }}} 289 // {{{ numRows() 290 291 function numRows($result) 292 { 293 // emulate numRows for Oracle. yuck. 294 if ($this->options['portability'] & DB_PORTABILITY_NUMROWS && 295 $result === $this->last_stmt) 296 { 297 $countquery = 'SELECT COUNT(*) FROM ('.$this->last_query.')'; 298 $save_query = $this->last_query; 299 $save_stmt = $this->last_stmt; 300 301 if (count($this->_data)) { 302 $smt = $this->prepare('SELECT COUNT(*) FROM ('.$this->last_query.')'); 303 $count = $this->execute($smt, $this->_data); 304 } else { 305 $count =& $this->query($countquery); 306 } 307 308 if (DB::isError($count) || 309 DB::isError($row = $count->fetchRow(DB_FETCHMODE_ORDERED))) 310 { 311 $this->last_query = $save_query; 312 $this->last_stmt = $save_stmt; 313 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 314 } 315 return $row[0]; 316 } 317 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 318 } 319 320 // }}} 321 // {{{ numCols() 322 323 /** 324 * Get the number of columns in a result set. 325 * 326 * @param $result oci8 result identifier 327 * 328 * @return int the number of columns per row in $result 329 */ 330 function numCols($result) 331 { 332 $cols = @OCINumCols($result); 333 if (!$cols) { 334 return $this->oci8RaiseError($result); 335 } 336 return $cols; 337 } 338 339 // }}} 340 // {{{ errorNative() 341 342 /** 343 * Get the native error code of the last error (if any) that occured 344 * on the current connection. This does not work, as OCIError does 345 * not work unless given a statement. If OCIError does return 346 * something, so will this. 347 * 348 * @return int native oci8 error code 349 */ 350 function errorNative() 351 { 352 if (is_resource($this->last_stmt)) { 353 $error = @OCIError($this->last_stmt); 354 } else { 355 $error = @OCIError($this->connection); 356 } 357 if (is_array($error)) { 358 return $error['code']; 359 } 360 return false; 361 } 362 363 // }}} 364 // {{{ prepare() 365 366 /** 367 * Prepares a query for multiple execution with execute(). 368 * 369 * With oci8, this is emulated. 370 * 371 * prepare() requires a generic query as string like <code> 372 * INSERT INTO numbers VALUES (?, ?, ?) 373 * </code>. The <kbd>?</kbd> characters are placeholders. 374 * 375 * Three types of placeholders can be used: 376 * + <kbd>?</kbd> a quoted scalar value, i.e. strings, integers 377 * + <kbd>!</kbd> value is inserted 'as is' 378 * + <kbd>&</kbd> requires a file name. The file's contents get 379 * inserted into the query (i.e. saving binary 380 * data in a db) 381 * 382 * Use backslashes to escape placeholder characters if you don't want 383 * them to be interpreted as placeholders. Example: <code> 384 * "UPDATE foo SET col=? WHERE col='over \& under'" 385 * </code> 386 * 387 * @param string $query query to be prepared 388 * @return mixed DB statement resource on success. DB_Error on failure. 389 */ 390 function prepare($query) 391 { 392 $tokens = preg_split('/((?<!\\\)[&?!])/', $query, -1, 393 PREG_SPLIT_DELIM_CAPTURE); 394 $binds = count($tokens) - 1; 395 $token = 0; 396 $types = array(); 397 $newquery = ''; 398 399 foreach ($tokens as $key => $val) { 400 switch ($val) { 401 case '?': 402 $types[$token++] = DB_PARAM_SCALAR; 403 unset($tokens[$key]); 404 break; 405 case '&': 406 $types[$token++] = DB_PARAM_OPAQUE; 407 unset($tokens[$key]); 408 break; 409 case '!': 410 $types[$token++] = DB_PARAM_MISC; 411 unset($tokens[$key]); 412 break; 413 default: 414 $tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val); 415 if ($key != $binds) { 416 $newquery .= $tokens[$key] . ':bind' . $token; 417 } else { 418 $newquery .= $tokens[$key]; 419 } 420 } 421 } 422 423 $this->last_query = $query; 424 $newquery = $this->modifyQuery($newquery); 425 if (!$stmt = @OCIParse($this->connection, $newquery)) { 426 return $this->oci8RaiseError(); 427 } 428 $this->prepare_types[(int)$stmt] = $types; 429 $this->manip_query[(int)$stmt] = DB::isManip($query); 430 return $stmt; 431 } 432 433 // }}} 434 // {{{ execute() 435 436 /** 437 * Executes a DB statement prepared with prepare(). 438 * 439 * @param resource $stmt a DB statement resource returned from prepare() 440 * @param mixed $data array, string or numeric data to be used in 441 * execution of the statement. Quantity of items 442 * passed must match quantity of placeholders in 443 * query: meaning 1 for non-array items or the 444 * quantity of elements in the array. 445 * @return int returns an oci8 result resource for successful 446 * SELECT queries, DB_OK for other successful queries. A DB error 447 * code is returned on failure. 448 * @see DB_oci::prepare() 449 */ 450 function &execute($stmt, $data = array()) 451 { 452 if (!is_array($data)) { 453 $data = array($data); 454 } 455 456 $this->_data = $data; 457 458 $types =& $this->prepare_types[(int)$stmt]; 459 if (count($types) != count($data)) { 460 $tmp =& $this->raiseError(DB_ERROR_MISMATCH); 461 return $tmp; 462 } 463 464 $i = 0; 465 foreach ($data as $key => $value) { 466 if ($types[$i] == DB_PARAM_MISC) { 467 /* 468 * Oracle doesn't seem to have the ability to pass a 469 * parameter along unchanged, so strip off quotes from start 470 * and end, plus turn two single quotes to one single quote, 471 * in order to avoid the quotes getting escaped by 472 * Oracle and ending up in the database. 473 */ 474 $data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]); 475 $data[$key] = str_replace("''", "'", $data[$key]); 476 } elseif ($types[$i] == DB_PARAM_OPAQUE) { 477 $fp = @fopen($data[$key], 'rb'); 478 if (!$fp) { 479 $tmp =& $this->raiseError(DB_ERROR_ACCESS_VIOLATION); 480 return $tmp; 481 } 482 $data[$key] = fread($fp, filesize($data[$key])); 483 fclose($fp); 484 } 485 if (!@OCIBindByName($stmt, ':bind' . $i, $data[$key], -1)) { 486 $tmp = $this->oci8RaiseError($stmt); 487 return $tmp; 488 } 489 $i++; 490 } 491 if ($this->autoCommit) { 492 $success = @OCIExecute($stmt, OCI_COMMIT_ON_SUCCESS); 493 } else { 494 $success = @OCIExecute($stmt, OCI_DEFAULT); 495 } 496 if (!$success) { 497 $tmp = $this->oci8RaiseError($stmt); 498 return $tmp; 499 } 500 $this->last_stmt = $stmt; 501 if ($this->manip_query[(int)$stmt]) { 502 $tmp = DB_OK; 503 } else { 504 $tmp =& new DB_result($this, $stmt); 505 } 506 return $tmp; 507 } 508 509 // }}} 510 // {{{ autoCommit() 511 512 /** 513 * Enable/disable automatic commits 514 * 515 * @param $onoff true/false whether to autocommit 516 */ 517 function autoCommit($onoff = false) 518 { 519 $this->autoCommit = (bool)$onoff;; 520 return DB_OK; 521 } 522 523 // }}} 524 // {{{ commit() 525 526 /** 527 * Commit transactions on the current connection 528 * 529 * @return DB_ERROR or DB_OK 530 */ 531 function commit() 532 { 533 $result = @OCICommit($this->connection); 534 if (!$result) { 535 return $this->oci8RaiseError(); 536 } 537 return DB_OK; 538 } 539 540 // }}} 541 // {{{ rollback() 542 543 /** 544 * Roll back all uncommitted transactions on the current connection. 545 * 546 * @return DB_ERROR or DB_OK 547 */ 548 function rollback() 549 { 550 $result = @OCIRollback($this->connection); 551 if (!$result) { 552 return $this->oci8RaiseError(); 553 } 554 return DB_OK; 555 } 556 557 // }}} 558 // {{{ affectedRows() 559 560 /** 561 * Gets the number of rows affected by the last query. 562 * if the last query was a select, returns 0. 563 * 564 * @return number of rows affected by the last query or DB_ERROR 565 */ 566 function affectedRows() 567 { 568 if ($this->last_stmt === false) { 569 return $this->oci8RaiseError(); 570 } 571 $result = @OCIRowCount($this->last_stmt); 572 if ($result === false) { 573 return $this->oci8RaiseError($this->last_stmt); 574 } 575 return $result; 576 } 577 578 // }}} 579 // {{{ modifyQuery() 580 581 function modifyQuery($query) 582 { 583 // "SELECT 2+2" must be "SELECT 2+2 FROM dual" in Oracle 584 if (preg_match('/^\s*SELECT/i', $query) && 585 !preg_match('/\sFROM\s/i', $query)) { 586 $query .= ' FROM dual'; 587 } 588 return $query; 589 } 590 591 // }}} 592 // {{{ modifyLimitQuery() 593 594 /** 595 * Emulate the row limit support altering the query 596 * 597 * @param string $query The query to treat 598 * @param int $from The row to start to fetch from 599 * @param int $count The offset 600 * @return string The modified query 601 * 602 * @author Tomas V.V.Cox <cox@idecnet.com> 603 */ 604 function modifyLimitQuery($query, $from, $count, $params = array()) 605 { 606 // Let Oracle return the name of the columns instead of 607 // coding a "home" SQL parser 608 609 if (count($params)) { 610 $result = $this->prepare("SELECT * FROM ($query) " 611 . 'WHERE NULL = NULL'); 612 $tmp =& $this->execute($result, $params); 613 } else { 614 $q_fields = "SELECT * FROM ($query) WHERE NULL = NULL"; 615 616 if (!$result = @OCIParse($this->connection, $q_fields)) { 617 $this->last_query = $q_fields; 618 return $this->oci8RaiseError(); 619 } 620 if (!@OCIExecute($result, OCI_DEFAULT)) { 621 $this->last_query = $q_fields; 622 return $this->oci8RaiseError($result); 623 } 624 } 625 626 $ncols = OCINumCols($result); 627 $cols = array(); 628 for ( $i = 1; $i <= $ncols; $i++ ) { 629 $cols[] = '"' . OCIColumnName($result, $i) . '"'; 630 } 631 $fields = implode(', ', $cols); 632 // XXX Test that (tip by John Lim) 633 //if (preg_match('/^\s*SELECT\s+/is', $query, $match)) { 634 // // Introduce the FIRST_ROWS Oracle query optimizer 635 // $query = substr($query, strlen($match[0]), strlen($query)); 636 // $query = "SELECT /* +FIRST_ROWS */ " . $query; 637 //} 638 639 // Construct the query 640 // more at: http://marc.theaimsgroup.com/?l=php-db&m=99831958101212&w=2 641 // Perhaps this could be optimized with the use of Unions 642 $query = "SELECT $fields FROM". 643 " (SELECT rownum as linenum, $fields FROM". 644 " ($query)". 645 ' WHERE rownum <= '. ($from + $count) . 646 ') WHERE linenum >= ' . ++$from; 647 return $query; 648 } 649 650 // }}} 651 // {{{ nextId() 652 653 /** 654 * Returns the next free id in a sequence 655 * 656 * @param string $seq_name name of the sequence 657 * @param boolean $ondemand when true, the seqence is automatically 658 * created if it does not exist 659 * 660 * @return int the next id number in the sequence. DB_Error if problem. 661 * 662 * @internal 663 * @see DB_common::nextID() 664 * @access public 665 */ 666 function nextId($seq_name, $ondemand = true) 667 { 668 $seqname = $this->getSequenceName($seq_name); 669 $repeat = 0; 670 do { 671 $this->expectError(DB_ERROR_NOSUCHTABLE); 672 $result =& $this->query("SELECT $seqname}.nextval FROM dual"); 673 $this->popExpect(); 674 if ($ondemand && DB::isError($result) && 675 $result->getCode() == DB_ERROR_NOSUCHTABLE) { 676 $repeat = 1; 677 $result = $this->createSequence($seq_name); 678 if (DB::isError($result)) { 679 return $this->raiseError($result); 680 } 681 } else { 682 $repeat = 0; 683 } 684 } while ($repeat); 685 if (DB::isError($result)) { 686 return $this->raiseError($result); 687 } 688 $arr = $result->fetchRow(DB_FETCHMODE_ORDERED); 689 return $arr[0]; 690 } 691 692 /** 693 * Creates a new sequence 694 * 695 * @param string $seq_name name of the new sequence 696 * 697 * @return int DB_OK on success. A DB_Error object is returned if 698 * problems arise. 699 * 700 * @internal 701 * @see DB_common::createSequence() 702 * @access public 703 */ 704 function createSequence($seq_name) 705 { 706 $seqname = $this->getSequenceName($seq_name); 707 return $this->query("CREATE SEQUENCE $seqname}"); 708 } 709 710 // }}} 711 // {{{ dropSequence() 712 713 /** 714 * Deletes a sequence 715 * 716 * @param string $seq_name name of the sequence to be deleted 717 * 718 * @return int DB_OK on success. DB_Error if problems. 719 * 720 * @internal 721 * @see DB_common::dropSequence() 722 * @access public 723 */ 724 function dropSequence($seq_name) 725 { 726 $seqname = $this->getSequenceName($seq_name); 727 return $this->query("DROP SEQUENCE $seqname}"); 728 } 729 730 // }}} 731 // {{{ oci8RaiseError() 732 733 /** 734 * Gather information about an error, then use that info to create a 735 * DB error object and finally return that object. 736 * 737 * @param integer $errno PEAR error number (usually a DB constant) if 738 * manually raising an error 739 * @return object DB error object 740 * @see DB_common::errorCode() 741 * @see DB_common::raiseError() 742 */ 743 function oci8RaiseError($errno = null) 744 { 745 if ($errno === null) { 746 $error = @OCIError($this->connection); 747 return $this->raiseError($this->errorCode($error['code']), 748 null, null, null, $error['message']); 749 } elseif (is_resource($errno)) { 750 $error = @OCIError($errno); 751 return $this->raiseError($this->errorCode($error['code']), 752 null, null, null, $error['message']); 753 } 754 return $this->raiseError($this->errorCode($errno)); 755 } 756 757 // }}} 758 // {{{ getSpecialQuery() 759 760 /** 761 * Returns the query needed to get some backend info 762 * @param string $type What kind of info you want to retrieve 763 * @return string The SQL query string 764 */ 765 function getSpecialQuery($type) 766 { 767 switch ($type) { 768 case 'tables': 769 return 'SELECT table_name FROM user_tables'; 770 default: 771 return null; 772 } 773 } 774 775 // }}} 776 // {{{ tableInfo() 777 778 /** 779 * Returns information about a table or a result set. 780 * 781 * NOTE: only supports 'table' and 'flags' if <var>$result</var> 782 * is a table name. 783 * 784 * NOTE: flags won't contain index information. 785 * 786 * @param object|string $result DB_result object from a query or a 787 * string containing the name of a table 788 * @param int $mode a valid tableInfo mode 789 * @return array an associative array with the information requested 790 * or an error object if something is wrong 791 * @access public 792 * @internal 793 * @see DB_common::tableInfo() 794 */ 795 function tableInfo($result, $mode = null) 796 { 797 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 798 $case_func = 'strtolower'; 799 } else { 800 $case_func = 'strval'; 801 } 802 803 if (is_string($result)) { 804 /* 805 * Probably received a table name. 806 * Create a result resource identifier. 807 */ 808 $result = strtoupper($result); 809 $q_fields = 'SELECT column_name, data_type, data_length, ' 810 . 'nullable ' 811 . 'FROM user_tab_columns ' 812 . "WHERE table_name='$result' ORDER BY column_id"; 813 814 $this->last_query = $q_fields; 815 816 if (!$stmt = @OCIParse($this->connection, $q_fields)) { 817 return $this->oci8RaiseError(DB_ERROR_NEED_MORE_DATA); 818 } 819 if (!@OCIExecute($stmt, OCI_DEFAULT)) { 820 return $this->oci8RaiseError($stmt); 821 } 822 823 $i = 0; 824 while (@OCIFetch($stmt)) { 825 $res[$i]['table'] = $case_func($result); 826 $res[$i]['name'] = $case_func(@OCIResult($stmt, 1)); 827 $res[$i]['type'] = @OCIResult($stmt, 2); 828 $res[$i]['len'] = @OCIResult($stmt, 3); 829 $res[$i]['flags'] = (@OCIResult($stmt, 4) == 'N') ? 'not_null' : ''; 830 831 if ($mode & DB_TABLEINFO_ORDER) { 832 $res['order'][$res[$i]['name']] = $i; 833 } 834 if ($mode & DB_TABLEINFO_ORDERTABLE) { 835 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 836 } 837 $i++; 838 } 839 840 if ($mode) { 841 $res['num_fields'] = $i; 842 } 843 @OCIFreeStatement($stmt); 844 845 } else { 846 if (isset($result->result)) { 847 /* 848 * Probably received a result object. 849 * Extract the result resource identifier. 850 */ 851 $result = $result->result; 852 } else { 853 /* 854 * ELSE, probably received a result resource identifier. 855 * Deprecated. Here for compatibility only. 856 */ 857 } 858 859 if ($result === $this->last_stmt) { 860 $count = @OCINumCols($result); 861 862 for ($i=0; $i<$count; $i++) { 863 $res[$i]['table'] = ''; 864 $res[$i]['name'] = $case_func(@OCIColumnName($result, $i+1)); 865 $res[$i]['type'] = @OCIColumnType($result, $i+1); 866 $res[$i]['len'] = @OCIColumnSize($result, $i+1); 867 $res[$i]['flags'] = ''; 868 869 if ($mode & DB_TABLEINFO_ORDER) { 870 $res['order'][$res[$i]['name']] = $i; 871 } 872 if ($mode & DB_TABLEINFO_ORDERTABLE) { 873 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 874 } 875 } 876 877 if ($mode) { 878 $res['num_fields'] = $count; 879 } 880 881 } else { 882 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 883 } 884 } 885 return $res; 886 } 887 888 // }}} 889 890 } 891 892 /* 893 * Local variables: 894 * tab-width: 4 895 * c-basic-offset: 4 896 * End: 897 */ 898 899 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sat Feb 24 14:40:03 2007 | par Balluche grâce à PHPXref 0.7 |