| [ Index ] |
|
Code source de PHP PEAR 1.4.5 |
1 <?php 2 // +----------------------------------------------------------------------+ 3 // | PHP Version 4 | 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox, | 6 // | Stig. S. Bakken, Lukas Smith | 7 // | All rights reserved. | 8 // +----------------------------------------------------------------------+ 9 // | MDB is a merge of PEAR DB and Metabases that provides a unified DB | 10 // | API as well as database abstraction for PHP applications. | 11 // | This LICENSE is in the BSD license style. | 12 // | | 13 // | Redistribution and use in source and binary forms, with or without | 14 // | modification, are permitted provided that the following conditions | 15 // | are met: | 16 // | | 17 // | Redistributions of source code must retain the above copyright | 18 // | notice, this list of conditions and the following disclaimer. | 19 // | | 20 // | Redistributions in binary form must reproduce the above copyright | 21 // | notice, this list of conditions and the following disclaimer in the | 22 // | documentation and/or other materials provided with the distribution. | 23 // | | 24 // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | 25 // | Lukas Smith nor the names of his contributors may be used to endorse | 26 // | or promote products derived from this software without specific prior| 27 // | written permission. | 28 // | | 29 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 30 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 31 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 32 // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 33 // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 34 // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 35 // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| 36 // | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 37 // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 38 // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| 39 // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 40 // | POSSIBILITY OF SUCH DAMAGE. | 41 // +----------------------------------------------------------------------+ 42 // | Author: Lukas Smith <smith@backendmedia.com> | 43 // +----------------------------------------------------------------------+ 44 45 // $Id: oci8.php,v 1.21.4.24 2004/03/31 16:02:40 lsmith Exp $ 46 47 require_once ('MDB/Common.php'); 48 49 /** 50 * MDB OCI8 driver 51 * 52 * Notes: 53 * - when fetching in associative mode all keys are uppercased which is not the 54 * intenteded behavior. Due to BC issues this will not be changed in MDB 1.x 55 * however. 56 * 57 * - createDatabase and dropDatabase are not supported 58 * 59 * - Text fields with unspecified length limit are created as VARCHAR with an 60 * optional limit that may not exceed 4000 characters. 61 * 62 * - date fields are emulated with date fields with time set to 00:00:00. 63 time fields are emulated with date fields with the day set to 0001-01-01. 64 * 65 * - The numRows method is emulated by fetching all the rows into memory. 66 * Avoid using it if for queries with large result sets. 67 * 68 * - Oracle does not provide direct support for returning result sets restricted 69 to a given range. Such support is emulated in the MDB oci8 driver. 70 * 71 * - Storing data in large object fields has to be done in two phases: first the 72 fields are initialized using a INSERT or UPDATE query that sets the fields 73 to an empty value, then the data values are uploaded to the large objects 74 returned by reference from the executed queries. 75 * Besides the fact that only INSERT and UPDATE queries are supported to 76 upload large object data values, only UPDATE queries that affect only one 77 row will set the large object fields correctly. 78 * 79 * - The driver alterTable method does not implement table or column renaming. 80 * 81 * @package MDB 82 * @category Database 83 * @author Lukas Smith <smith@backendmedia.com> 84 */ 85 class MDB_oci8 extends MDB_Common { 86 var $connection = 0; 87 var $connected_user; 88 var $connected_password; 89 90 var $escape_quotes = "'"; 91 92 var $uncommitedqueries = 0; 93 94 var $results = array(); 95 var $current_row = array(); 96 var $columns = array(); 97 var $rows = array(); 98 var $limits = array(); 99 var $row_buffer = array(); 100 var $highest_fetched_row = array(); 101 102 // {{{ constructor 103 104 /** 105 * Constructor 106 */ 107 function MDB_oci8() 108 { 109 $this->MDB_Common(); 110 $this->phptype = 'oci8'; 111 $this->dbsyntax = 'oci8'; 112 113 $this->supported['Sequences'] = 1; 114 $this->supported['Indexes'] = 1; 115 $this->supported['SummaryFunctions'] = 1; 116 $this->supported['OrderByText'] = 1; 117 $this->supported['CurrId'] = 1; 118 $this->supported["AffectedRows"]= 1; 119 $this->supported['Transactions'] = 1; 120 $this->supported['SelectRowRanges'] = 1; 121 $this->supported['LOBs'] = 1; 122 $this->supported['Replace'] = 1; 123 $this->supported['SubSelects'] = 1; 124 125 $this->options['DBAUser'] = FALSE; 126 $this->options['DBAPassword'] = FALSE; 127 128 $this->errorcode_map = array( 129 1 => MDB_ERROR_CONSTRAINT, 130 900 => MDB_ERROR_SYNTAX, 131 904 => MDB_ERROR_NOSUCHFIELD, 132 921 => MDB_ERROR_SYNTAX, 133 923 => MDB_ERROR_SYNTAX, 134 942 => MDB_ERROR_NOSUCHTABLE, 135 955 => MDB_ERROR_ALREADY_EXISTS, 136 1400 => MDB_ERROR_CONSTRAINT_NOT_NULL, 137 1407 => MDB_ERROR_CONSTRAINT_NOT_NULL, 138 1476 => MDB_ERROR_DIVZERO, 139 1722 => MDB_ERROR_INVALID_NUMBER, 140 2289 => MDB_ERROR_NOSUCHTABLE, 141 2291 => MDB_ERROR_CONSTRAINT, 142 2449 => MDB_ERROR_CONSTRAINT, 143 ); 144 } 145 146 // }}} 147 // {{{ errorNative() 148 149 /** 150 * Get the native error code of the last error (if any) that 151 * occured on the current connection. 152 * 153 * @access public 154 * @return int native oci8 error code 155 */ 156 function errorNative($statement = NULL) 157 { 158 if (is_resource($statement)) { 159 $error = @OCIError($statement); 160 } else { 161 $error = @OCIError($this->connection); 162 } 163 if (is_array($error)) { 164 return($error['code']); 165 } 166 return(FALSE); 167 } 168 169 // }}} 170 // {{{ oci8RaiseError() 171 172 /** 173 * This method is used to communicate an error and invoke error 174 * callbacks etc. Basically a wrapper for MDB::raiseError 175 * that checks for native error msgs. 176 * 177 * @param integer $errno error code 178 * @param string $message userinfo message 179 * @return object a PEAR error object 180 * @access public 181 * @see PEAR_Error 182 */ 183 function oci8RaiseError($errno = NULL, $message = NULL) 184 { 185 if ($errno === NULL) { 186 if ($this->connection) { 187 $error = @OCIError($this->connection); 188 } else { 189 $error = @OCIError(); 190 } 191 return($this->raiseError($this->errorCode($error['code']), 192 NULL, NULL, $message, $error['message'])); 193 } elseif (is_resource($errno)) { 194 $error = @OCIError($errno); 195 return($this->raiseError($this->errorCode($error['code']), 196 NULL, NULL, $message, $error['message'])); 197 } 198 return($this->raiseError($this->errorCode($errno), NULL, NULL, $message)); 199 } 200 201 // }}} 202 // {{{ autoCommit() 203 204 /** 205 * Define whether database changes done on the database be automatically 206 * committed. This function may also implicitly start or end a transaction. 207 * 208 * @param boolean $auto_commit flag that indicates whether the database 209 * changes should be committed right after 210 * executing every query statement. If this 211 * argument is 0 a transaction implicitly 212 * started. Otherwise, if a transaction is 213 * in progress it is ended by committing any 214 * database changes that were pending. 215 * @access public 216 * @return mixed MDB_OK on success, a MDB error on failure 217 */ 218 function autoCommit($auto_commit) 219 { 220 $this->debug('AutoCommit: '.($auto_commit ? 'On' : 'Off')); 221 if ($this->auto_commit == $auto_commit) { 222 return(MDB_OK); 223 } 224 if ($this->connection && $auto_commit && MDB::isError($commit = $this->commit())) { 225 return($commit); 226 } 227 $this->auto_commit = $auto_commit; 228 $this->in_transaction = !$auto_commit; 229 return(MDB_OK); 230 } 231 232 // }}} 233 // {{{ commit() 234 235 /** 236 * Commit the database changes done during a transaction that is in 237 * progress. This function may only be called when auto-committing is 238 * disabled, otherwise it will fail. Therefore, a new transaction is 239 * implicitly started after committing the pending changes. 240 * 241 * @access public 242 * @return mixed MDB_OK on success, a MDB error on failure 243 */ 244 function commit() 245 { 246 $this->debug('Commit Transaction'); 247 if (!isset($this->supported['Transactions'])) { 248 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 249 'Commit transactions: transactions are not in use')); 250 } 251 if ($this->auto_commit) { 252 return($this->raiseError(MDB_ERROR, NULL, NULL, 253 'Commit transactions: transaction changes are being auto commited')); 254 } 255 if ($this->uncommitedqueries) { 256 if (!@OCICommit($this->connection)) { 257 return($this->oci8RaiseError(NULL, 258 'Commit transactions: Could not commit pending transaction: '."$message. Error: ".$error['code'].' ('.$error['message'].')')); 259 } 260 $this->uncommitedqueries = 0; 261 } 262 return(MDB_OK); 263 } 264 265 // }}} 266 // {{{ rollback() 267 268 /** 269 * Cancel any database changes done during a transaction that is in 270 * progress. This function may only be called when auto-committing is 271 * disabled, otherwise it will fail. Therefore, a new transaction is 272 * implicitly started after canceling the pending changes. 273 * 274 * @access public 275 * @return mixed MDB_OK on success, a MDB error on failure 276 */ 277 function rollback() 278 { 279 $this->debug('Rollback Transaction'); 280 if ($this->auto_commit) { 281 return($this->raiseError(MDB_ERROR, NULL, NULL, 282 'Rollback transactions: transactions can not be rolled back when changes are auto commited')); 283 } 284 if ($this->uncommitedqueries) { 285 if (!@OCIRollback($this->connection)) { 286 return($this->oci8RaiseError(NULL, 287 'Rollback transaction: Could not rollback pending transaction')); 288 } 289 $this->uncommitedqueries = 0; 290 } 291 return(MDB_OK); 292 } 293 294 // }}} 295 // {{{ connect() 296 297 /** 298 * Connect to the database 299 * 300 * @return TRUE on success, MDB_Error on failure 301 */ 302 function connect($user = NULL , $password = NULL, $persistent = NULL) 303 { 304 if($user === NULL) { 305 $user = $this->user; 306 } 307 if($password === NULL) { 308 $password = $this->password; 309 } 310 if($persistent === NULL) { 311 $persistent = $this->getOption('persistent'); 312 } 313 if (isset($this->host)) { 314 $sid = $this->host; 315 } else { 316 $sid = getenv('ORACLE_SID'); 317 } 318 if(!strcmp($sid, '')) { 319 return($this->raiseError(MDB_ERROR, NULL, NULL, 320 'Connect: it was not specified a valid Oracle Service IDentifier (SID)')); 321 } 322 if($this->connection != 0) { 323 if (!strcmp($this->connected_user, $user) 324 && !strcmp($this->connected_password, $password) 325 && $this->opened_persistent == $persistent) 326 { 327 return(MDB_OK); 328 } 329 $this->_close(); 330 } 331 332 if(!PEAR::loadExtension($this->phptype)) { 333 return(PEAR::raiseError(NULL, MDB_ERROR_NOT_FOUND, 334 NULL, NULL, 'extension '.$this->phptype.' is not compiled into PHP', 335 'MDB_Error', TRUE)); 336 } 337 338 if (isset($this->options['HOME'])) { 339 putenv('ORACLE_HOME='.$this->options['HOME']); 340 } 341 putenv('ORACLE_SID='.$sid); 342 $function = ($persistent ? 'OCIPLogon' : 'OCINLogon'); 343 if (!function_exists($function)) { 344 return($this->raiseError(MDB_ERROR, NULL, NULL, 345 'Connect: Oracle OCI API support is not available in this PHP configuration')); 346 } 347 if (!($this->connection = @$function($user, $password, $sid))) { 348 return($this->oci8RaiseError(NULL, 349 'Connect: Could not connect to Oracle server')); 350 } 351 if (MDB::isError($doquery = $this->_doQuery("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'"))) { 352 $this->_close(); 353 return($doquery); 354 } 355 if (MDB::isError($doquery = $this->_doQuery("ALTER SESSION SET NLS_NUMERIC_CHARACTERS='. '"))) { 356 $this->_close(); 357 return($doquery); 358 } 359 360 $this->connected_user = $user; 361 $this->connected_password = $password; 362 $this->opened_persistent = $persistent; 363 return(MDB_OK); 364 } 365 366 // }}} 367 // {{{ _close() 368 369 /** 370 * all the RDBMS specific things needed close a DB connection 371 * 372 * @access private 373 */ 374 function _close() 375 { 376 if ($this->connection != 0) { 377 @OCILogOff($this->connection); 378 $this->connection = 0; 379 $this->affected_rows = -1; 380 $this->uncommitedqueries = 0; 381 } 382 } 383 384 // }}} 385 // {{{ _doQuery() 386 387 /** 388 * all the RDBMS specific things needed close a DB connection 389 * 390 * @access private 391 */ 392 function _doQuery($query, $first = 0, $limit = 0, $prepared_query = 0) 393 { 394 $lobs = 0; 395 $success = MDB_OK; 396 $result = 0; 397 $descriptors = array(); 398 if ($prepared_query) { 399 $columns = ''; 400 $variables = ''; 401 for(reset($this->clobs[$prepared_query]), $clob = 0; 402 $clob < count($this->clobs[$prepared_query]); 403 $clob++, next($this->clobs[$prepared_query])) 404 { 405 $position = key($this->clobs[$prepared_query]); 406 if (gettype($descriptors[$position] = @OCINewDescriptor($this->connection, OCI_D_LOB)) != 'object') { 407 $success = $this->raiseError(MDB_ERROR, NULL, NULL, 408 'Do query: Could not create descriptor for clob parameter'); 409 break; 410 } 411 $columns.= ($lobs == 0 ? ' RETURNING ' : ',').$this->prepared_queries[$prepared_query-1]['Fields'][$position-1]; 412 $variables.= ($lobs == 0 ? ' INTO ' : ',').':clob'.$position; 413 $lobs++; 414 } 415 if (!MDB::isError($success)) { 416 for(reset($this->blobs[$prepared_query]), $blob = 0;$blob < count($this->blobs[$prepared_query]);$blob++, next($this->blobs[$prepared_query])) { 417 $position = key($this->blobs[$prepared_query]); 418 if (gettype($descriptors[$position] = @OCINewDescriptor($this->connection, OCI_D_LOB)) != 'object') { 419 $success = $this->raiseError(MDB_ERROR, NULL, NULL, 420 'Do query: Could not create descriptor for blob parameter'); 421 break; 422 } 423 $columns.= ($lobs == 0 ? ' RETURNING ' : ',').$this->prepared_queries[$prepared_query-1]['Fields'][$position-1]; 424 $variables.= ($lobs == 0 ? ' INTO ' : ',').':blob'.$position; 425 $lobs++; 426 } 427 $query.= $columns.$variables; 428 } 429 } 430 if (!MDB::isError($success)) { 431 if (($statement = @OCIParse($this->connection, $query))) { 432 if ($lobs) { 433 for(reset($this->clobs[$prepared_query]), $clob = 0;$clob < count($this->clobs[$prepared_query]);$clob++, next($this->clobs[$prepared_query])) { 434 $position = key($this->clobs[$prepared_query]); 435 if (!@OCIBindByName($statement, ':clob'.$position, $descriptors[$position], -1, OCI_B_CLOB)) { 436 $success = $this->oci8RaiseError(NULL, 437 'Do query: Could not bind clob upload descriptor'); 438 break; 439 } 440 } 441 if (!MDB::isError($success)) { 442 for(reset($this->blobs[$prepared_query]), $blob = 0; 443 $blob < count($this->blobs[$prepared_query]); 444 $blob++, next($this->blobs[$prepared_query])) 445 { 446 $position = key($this->blobs[$prepared_query]); 447 if (!@OCIBindByName($statement, ':blob'.$position, $descriptors[$position], -1, OCI_B_BLOB)) { 448 $success = $this->oci8RaiseError(NULL, 449 'Do query: Could not bind blob upload descriptor'); 450 break; 451 } 452 } 453 } 454 } 455 if (!MDB::isError($success)) { 456 if (($result = @OCIExecute($statement, ($lobs == 0 && $this->auto_commit) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT))) { 457 if ($lobs) { 458 for(reset($this->clobs[$prepared_query]), $clob = 0; 459 $clob < count($this->clobs[$prepared_query]); 460 $clob++, next($this->clobs[$prepared_query])) 461 { 462 $position = key($this->clobs[$prepared_query]); 463 $clob_stream = $this->prepared_queries[$prepared_query-1]['Values'][$position-1]; 464 for($value = '';!$this->endOfLOB($clob_stream);) { 465 if ($this->readLOB($clob_stream, $data, $this->getOption('lob_buffer_length')) < 0) { 466 $success = $this->raiseError(); 467 break; 468 } 469 $value.= $data; 470 } 471 if (!MDB::isError($success) && !$descriptors[$position]->save($value)) { 472 $success = $this->oci8RaiseError(NULL, 473 'Do query: Could not upload clob data'); 474 } 475 } 476 if (!MDB::isError($success)) { 477 for(reset($this->blobs[$prepared_query]), $blob = 0;$blob < count($this->blobs[$prepared_query]);$blob++, next($this->blobs[$prepared_query])) { 478 $position = key($this->blobs[$prepared_query]); 479 $blob_stream = $this->prepared_queries[$prepared_query-1]['Values'][$position-1]; 480 for($value = '';!$this->endOfLOB($blob_stream);) { 481 if ($this->readLOB($blob_stream, $data, $this->getOption('lob_buffer_length')) < 0) { 482 $success = $this->raiseError(); 483 break; 484 } 485 $value.= $data; 486 } 487 if (!MDB::isError($success) && !$descriptors[$position]->save($value)) { 488 $success = $this->oci8RaiseError(NULL, 489 'Do query: Could not upload blob data'); 490 } 491 } 492 } 493 } 494 if ($this->auto_commit) { 495 if ($lobs) { 496 if (MDB::isError($success)) { 497 if (!@OCIRollback($this->connection)) { 498 $success = $this->oci8RaiseError(NULL, 499 'Do query: '.$success->getUserinfo().' and then could not rollback LOB updating transaction'); 500 } 501 } else { 502 if (!@OCICommit($this->connection)) { 503 $success = $this->oci8RaiseError(NULL, 504 'Do query: Could not commit pending LOB updating transaction'); 505 } 506 } 507 } 508 } else { 509 $this->uncommitedqueries++; 510 } 511 if (!MDB::isError($success)) { 512 switch (@OCIStatementType($statement)) { 513 case 'SELECT': 514 $result_value = intval($statement); 515 $this->current_row[$result_value] = -1; 516 if ($limit > 0) { 517 $this->limits[$result_value] = array($first, $limit, 0); 518 } 519 $this->highest_fetched_row[$result_value] = -1; 520 break; 521 default: 522 $this->affected_rows = @OCIRowCount($statement); 523 @OCIFreeCursor($statement); 524 break; 525 } 526 $result = $statement; 527 } 528 } else { 529 return($this->oci8RaiseError($statement, 'Do query: Could not execute query')); 530 } 531 } 532 } else { 533 return($this->oci8RaiseError(NULL, 'Do query: Could not parse query')); 534 } 535 } 536 for(reset($descriptors), $descriptor = 0; 537 $descriptor < count($descriptors); 538 $descriptor++, next($descriptors)) 539 { 540 @OCIFreeDesc($descriptors[key($descriptors)]); 541 } 542 return($result); 543 } 544 545 // }}} 546 // {{{ query() 547 548 /** 549 * Send a query to the database and return any results 550 * 551 * @access public 552 * @param string $query the SQL query 553 * @param array $types array that contains the types of the columns in 554 * the result set 555 * @return mixed a result handle or MDB_OK on success, a MDB error on failure 556 */ 557 function query($query, $types = NULL) 558 { 559 $this->debug("Query: $query"); 560 $this->last_query = $query; 561 $first = $this->first_selected_row; 562 $limit = $this->selected_row_limit; 563 $this->first_selected_row = $this->selected_row_limit = 0; 564 if (MDB::isError($connect = $this->connect())) { 565 return($connect); 566 } 567 if(!MDB::isError($result = $this->_doQuery($query, $first, $limit))) { 568 if ($types != NULL) { 569 if (!is_array($types)) { 570 $types = array($types); 571 } 572 if (MDB::isError($err = $this->setResultTypes($result, $types))) { 573 $this->freeResult($result); 574 return($err); 575 } 576 } 577 return($result); 578 } 579 return($this->oci8RaiseError()); 580 } 581 582 // }}} 583 // {{{ _executePreparedQuery() 584 585 /** 586 * Execute a prepared query statement. 587 * 588 * @param int $prepared_query argument is a handle that was returned by 589 * the function prepareQuery() 590 * @param string $query query to be executed 591 * @param array $types array that contains the types of the columns in 592 * the result set 593 * @return mixed a result handle or MDB_OK on success, a MDB error on failure 594 * @access private 595 */ 596 function _executePreparedQuery($prepared_query, $query) 597 { 598 $first = $this->first_selected_row; 599 $limit = $this->selected_row_limit; 600 $this->first_selected_row = $this->selected_row_limit = 0; 601 if (MDB::isError($connect = $this->connect())) { 602 return($connect); 603 } 604 return($this->_doQuery($query, $first, $limit, $prepared_query)); 605 } 606 607 // }}} 608 // {{{ _skipLimitOffset() 609 610 /** 611 * Skip the first row of a result set. 612 * 613 * @param resource $result 614 * @return mixed a result handle or MDB_OK on success, a MDB error on failure 615 * @access private 616 */ 617 function _skipLimitOffset($result) 618 { 619 $result_value = intval($result); 620 $first = $this->limits[$result_value][0]; 621 for(;$this->limits[$result_value][2] < $first;$this->limits[$result_value][2]++) { 622 if (!@OCIFetch($result)) { 623 $this->limits[$result_value][2] = $first; 624 return($this->raiseError(MDB_ERROR, NULL, NULL, 625 'Skip first rows: could not skip a query result row')); 626 } 627 } 628 return(MDB_OK); 629 } 630 631 // }}} 632 // {{{ getColumnNames() 633 634 /** 635 * Retrieve the names of columns returned by the DBMS in a query result. 636 * 637 * @param resource $result result identifier 638 * @return mixed an associative array variable 639 * that will hold the names of columns.The 640 * indexes of the array are the column names 641 * mapped to lower case and the values are the 642 * respective numbers of the columns starting 643 * from 0. Some DBMS may not return any 644 * columns when the result set does not 645 * contain any rows. 646 * 647 * a MDB error on failure 648 * @access public 649 */ 650 function getColumnNames($result) 651 { 652 $result_value = intval($result); 653 if (!isset($this->highest_fetched_row[$result_value])) { 654 return($this->raiseError(MDB_ERROR, NULL, NULL, 655 'Get column names: it was specified an inexisting result set')); 656 } 657 if (!isset($this->columns[$result_value])) { 658 $this->columns[$result_value] = array(); 659 $columns = @OCINumCols($result); 660 for($column = 0; $column < $columns; $column++) { 661 $field_name = @OCIColumnName($result, $column + 1); 662 if ($this->options['optimize'] == 'portability') { 663 $field_name = strtolower($field_name); 664 } 665 $this->columns[$result_value][$field_name] = $column; 666 } 667 } 668 return($this->columns[$result_value]); 669 } 670 671 // }}} 672 // {{{ numCols() 673 674 /** 675 * Count the number of columns returned by the DBMS in a query result. 676 * 677 * @param resource $result result identifier 678 * @return mixed integer value with the number of columns, a MDB error 679 * on failure 680 * @access public 681 */ 682 function numCols($result) 683 { 684 $result_value = intval($result); 685 if (!isset($this->highest_fetched_row[$result_value])) { 686 return($this->raiseError(MDB_ERROR, NULL, NULL, 687 'Number of columns: it was specified an inexisting result set')); 688 } 689 return(@OCINumCols($result)); 690 } 691 692 // }}} 693 // {{{ endOfResult() 694 695 /** 696 * check if the end of the result set has been reached 697 * 698 * @param resource $result result identifier 699 * @return mixed TRUE or FALSE on sucess, a MDB error on failure 700 * @access public 701 */ 702 function endOfResult($result) 703 { 704 $result_value = intval($result); 705 if (!isset($this->current_row[$result_value])) { 706 return($this->raiseError(MDB_ERROR, NULL, NULL, 707 'End of result: attempted to check the end of an unknown result')); 708 } 709 if (isset($this->results[$result_value]) && end($this->results[$result_value]) === FALSE) { 710 return(($this->highest_fetched_row[$result_value]-1) <= $this->current_row[$result_value]); 711 } 712 if (isset($this->row_buffer[$result_value])) { 713 return(!$this->row_buffer[$result_value]); 714 } 715 if (isset($this->limits[$result_value])) { 716 if (MDB::isError($this->_skipLimitOffset($result)) 717 || ($this->current_row[$result_value]) > $this->limits[$result_value][1] 718 ) { 719 return(TRUE); 720 } 721 } 722 if (@OCIFetchInto($result, $this->row_buffer[$result_value], OCI_RETURN_NULLS)) { 723 return(FALSE); 724 } 725 $this->row_buffer[$result_value] = FALSE; 726 return(TRUE); 727 } 728 729 // }}} 730 // {{{ _retrieveLob() 731 732 /** 733 * fetch a lob value from a result set 734 * 735 * @param int $lob handle to a lob created by the createLob() function 736 * @return mixed MDB_OK on success, a MDB error on failure 737 * @access private 738 */ 739 function _retrieveLob($lob) 740 { 741 if (!isset($this->lobs[$lob])) { 742 return($this->raiseError(MDB_ERROR, NULL, NULL, 743 'Retrieve LOB: it was not specified a valid lob')); 744 } 745 if (!isset($this->lobs[$lob]['Value'])) { 746 unset($lob_object); 747 $result = $this->lobs[$lob]['Result']; 748 $row = $this->lobs[$lob]['Row']; 749 $field = $this->lobs[$lob]['Field']; 750 $lob_object = $this->fetch($result, $row, $field); 751 if (MDB::isError($lob_object)) { 752 return $lob_object; 753 } 754 if (gettype($lob_object) != 'object') { 755 return($this->raiseError(MDB_ERROR, NULL, NULL, 756 'Retrieve LOB: attemped to retrieve LOB from non existing or NULL column')); 757 } 758 $this->lobs[$lob]['Value'] = $lob_object->load(); 759 } 760 return(MDB_OK); 761 } 762 763 // }}} 764 // {{{ fetch() 765 766 /** 767 * fetch value from a result set 768 * 769 * @param resource $result result identifier 770 * @param int $rownum number of the row where the data can be found 771 * @param int $colnum field number where the data can be found 772 * @return mixed string on success, a MDB error on failure 773 * @access public 774 */ 775 function fetch($result, $rownum, $colnum) 776 { 777 $fetchmode = is_numeric($colnum) ? MDB_FETCHMODE_ORDERED : MDB_FETCHMODE_ASSOC; 778 $row = $this->fetchInto($result, $fetchmode, $rownum); 779 if (MDB::isError($row)) { 780 return($row); 781 } 782 if (!array_key_exists($colnum, $row)) { 783 return(NULL); 784 } 785 return($row[$colnum]); 786 } 787 788 // }}} 789 // {{{ fetchClob() 790 791 /** 792 * fetch a clob value from a result set 793 * 794 * @param resource $result result identifier 795 * @param int $row number of the row where the data can be found 796 * @param int $field field number where the data can be found 797 * @return mixed content of the specified data cell, a MDB error on failure, 798 * a MDB error on failure 799 * @access public 800 */ 801 function fetchClob($result, $row, $field) 802 { 803 return($this->fetchLOB($result, $row, $field)); 804 } 805 806 // }}} 807 // {{{ fetchBlob() 808 /** 809 * fetch a blob value from a result set 810 * 811 * @param resource $result result identifier 812 * @param int $row number of the row where the data can be found 813 * @param int $field field number where the data can be found 814 * @return mixed content of the specified data cell, a MDB error on failure 815 * @access public 816 */ 817 function fetchBlob($result, $row, $field) 818 { 819 return($this->fetchLOB($result, $row, $field)); 820 } 821 822 // }}} 823 // {{{ resultIsNull() 824 825 /** 826 * Determine whether the value of a query result located in given row and 827 * field is a NULL. 828 * 829 * @param resource $result result identifier 830 * @param int $rownum number of the row where the data can be found 831 * @param int $field field number where the data can be found 832 * @return mixed TRUE or FALSE on success, a MDB error on failure 833 * @access public 834 */ 835 function resultIsNull($result, $rownum, $field) 836 { 837 $value = $this->fetch($result, $rownum, $field); 838 if (MDB::isError($value)) { 839 return($value); 840 } 841 return(!isset($value)); 842 } 843 844 // }}} 845 // {{{ convertResult() 846 847 /** 848 * convert a value to a RDBMS indepdenant MDB type 849 * 850 * @param mixed $value value to be converted 851 * @param int $type constant that specifies which type to convert to 852 * @return mixed converted value 853 * @access public 854 */ 855 function convertResult($value, $type) 856 { 857 switch ($type) { 858 case MDB_TYPE_DATE: 859 return(substr($value, 0, strlen('YYYY-MM-DD'))); 860 case MDB_TYPE_TIME: 861 return(substr($value, strlen('YYYY-MM-DD '), strlen('HH:MI:SS'))); 862 default: 863 return($this->_baseConvertResult($value, $type)); 864 } 865 } 866 867 // }}} 868 // {{{ numRows() 869 870 /** 871 * returns the number of rows in a result object 872 * 873 * @param ressource $result a valid result ressouce pointer 874 * @return mixed MDB_Error or the number of rows 875 * @access public 876 */ 877 function numRows($result) 878 { 879 $result_value = intval($result); 880 if (!isset($this->current_row[$result_value])) { 881 return($this->raiseError(MDB_ERROR, NULL, NULL, 882 'Number of rows: attemped to obtain the number of rows contained in an unknown query result')); 883 } 884 if (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]]) 885 || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== FALSE 886 ) { 887 if (isset($this->limits[$result_value])) { 888 if (MDB::isError($skipfirstrow = $this->_skipLimitOffset($result))) { 889 return($skipfirstrow); 890 } 891 } 892 if (isset($this->row_buffer[$result_value])) { 893 ++$this->highest_fetched_row[$result_value]; 894 $this->results[$result_value][$this->highest_fetched_row[$result_value]] 895 = $this->row_buffer[$result_value]; 896 unset($this->row_buffer[$result_value]); 897 } 898 if (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]]) 899 || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== FALSE 900 ) { 901 while((!isset($this->limits[$result_value]) 902 || ($this->highest_fetched_row[$result_value]+1) < $this->limits[$result_value][1] 903 ) 904 && @OCIFetchInto($result, $buffer, OCI_RETURN_NULLS) 905 ) { 906 ++$this->highest_fetched_row[$result_value]; 907 $this->results[$result_value][$this->highest_fetched_row[$result_value]] = $buffer; 908 } 909 ++$this->highest_fetched_row[$result_value]; 910 $this->results[$result_value][$this->highest_fetched_row[$result_value]] = FALSE; 911 } 912 } 913 return(max(0, $this->highest_fetched_row[$result_value])); 914 } 915 916 // }}} 917 // {{{ freeResult() 918 919 /** 920 * Free the internal resources associated with $result. 921 * 922 * @param $result result identifier 923 * @return bool TRUE on success, FALSE if $result is invalid 924 * @access public 925 */ 926 function freeResult($result) 927 { 928 $result_value = intval($result); 929 if (!isset($this->current_row[$result_value])) { 930 return($this->raiseError(MDB_ERROR, NULL, NULL, 931 'Free result: attemped to free an unknown query result')); 932 } 933 if(isset($this->highest_fetched_row[$result_value])) { 934 unset($this->highest_fetched_row[$result_value]); 935 } 936 if(isset($this->row_buffer[$result_value])) { 937 unset($this->row_buffer[$result_value]); 938 } 939 if(isset($this->limits[$result_value])) { 940 unset($this->limits[$result_value]); 941 } 942 if(isset($this->current_row[$result_value])) { 943 unset($this->current_row[$result_value]); 944 } 945 if(isset($this->results[$result_value])) { 946 unset($this->results[$result_value]); 947 } 948 if(isset($this->columns[$result_value])) { 949 unset($this->columns[$result_value]); 950 } 951 if(isset($this->result_types[$result_value])) { 952 unset($this->result_types[$result_value]); 953 } 954 return(@OCIFreeCursor($result)); 955 } 956 957 // }}} 958 // {{{ getTypeDeclaration() 959 960 /** 961 * Obtain DBMS specific native datatype as a string 962 * 963 * @param string $field associative array with the name of the properties 964 * of the field being declared as array indexes. Currently, the types 965 * of supported field properties are as follows: 966 * 967 * @return string with the correct RDBMS native type 968 * @access public 969 */ 970 function getTypeDeclaration($field) 971 { 972 switch ($field['type']) { 973 case 'integer': 974 return('INT'); 975 case 'text': 976 return('VARCHAR ('.(isset($field['length']) 977 ? $field['length'] : (isset($this->options['DefaultTextFieldLength']) 978 ? $this->options['DefaultTextFieldLength'] : 4000)).')'); 979 case 'boolean': 980 return('CHAR (1)'); 981 case 'date': 982 case 'time': 983 case 'timestamp': 984 return('DATE'); 985 case 'float': 986 return('NUMBER'); 987 case 'decimal': 988 return('NUMBER(*,'.$this->decimal_places.')'); 989 } 990 return(''); 991 } 992 993 // }}} 994 // {{{ getIntegerDeclaration() 995 996 /** 997 * Obtain DBMS specific SQL code portion needed to declare an integer type 998 * field to be used in statements like CREATE TABLE. 999 * 1000 * @param string $name name the field to be declared. 1001 * @param string $field associative array with the name of the properties 1002 * of the field being declared as array indexes. Id 1003 * ently, the types 1004 * of supported field properties are as follows: 1005 * 1006 * unsigned 1007 * Boolean flag that indicates whether the field should be 1008 * declared as unsigned integer if possible. 1009 * 1010 * default 1011 * Integer value to be used as default for this field. 1012 * 1013 * notnull 1014 * Boolean flag that indicates whether this field is constrained 1015 * to not be set to NULL. 1016 * @return string DBMS specific SQL code portion that should be used to 1017 * declare the specified field. 1018 * @access public 1019 */ 1020 function getIntegerDeclaration($name, $field) 1021 { 1022 if (isset($field['unsigned'])) 1023 $this->warning = "unsigned integer field \"$name\" is being declared as signed integer"; 1024 return("$name ".$this->getTypeDeclaration($field) 1025 .(isset($field['default']) ? ' DEFAULT '.$field['default'] : '') 1026 .(isset($field['notnull']) ? ' NOT NULL' : '')); 1027 } 1028 1029 // }}} 1030 // {{{ getTextDeclaration() 1031 1032 /** 1033 * Obtain DBMS specific SQL code portion needed to declare an text type 1034 * field to be used in statements like CREATE TABLE. 1035 * 1036 * @param string $name name the field to be declared. 1037 * @param string $field associative array with the name of the properties 1038 * of the field being declared as array indexes. Currently, the types 1039 * of supported field properties are as follows: 1040 * 1041 * length 1042 * Integer value that determines the maximum length of the text 1043 * field. If this argument is missing the field should be 1044 * declared to have the longest length allowed by the DBMS. 1045 * 1046 * default 1047 * Text value to be used as default for this field. 1048 * 1049 * notnull 1050 * Boolean flag that indicates whether this field is constrained 1051 * to not be set to NULL. 1052 * @return string DBMS specific SQL code portion that should be used to 1053 * declare the specified field. 1054 * @access public 1055 */ 1056 function getTextDeclaration($name, $field) 1057 { 1058 return("$name ".$this->getTypeDeclaration($field) 1059 .(isset($field['default']) ? ' DEFAULT '.$this->getTextValue($field['default']) : '') 1060 .(isset($field['notnull']) ? ' NOT NULL' : '')); 1061 } 1062 1063 // }}} 1064 // {{{ getClobDeclaration() 1065 1066 /** 1067 * Obtain DBMS specific SQL code portion needed to declare an character 1068 * large object type field to be used in statements like CREATE TABLE. 1069 * 1070 * @param string $name name the field to be declared. 1071 * @param string $field associative array with the name of the properties 1072 * of the field being declared as array indexes. Currently, the types 1073 * of supported field properties are as follows: 1074 * 1075 * length 1076 * Integer value that determines the maximum length of the large 1077 * object field. If this argument is missing the field should be 1078 * declared to have the longest length allowed by the DBMS. 1079 * 1080 * notnull 1081 * Boolean flag that indicates whether this field is constrained 1082 * to not be set to NULL. 1083 * @return string DBMS specific SQL code portion that should be used to 1084 * declare the specified field. 1085 * @access public 1086 */ 1087 function getClobDeclaration($name, $field) 1088 { 1089 return("$name CLOB".(isset($field['notnull']) ? ' NOT NULL' : '')); 1090 } 1091 1092 // }}} 1093 // {{{ getBlobDeclaration() 1094 1095 /** 1096 * Obtain DBMS specific SQL code portion needed to declare an binary large 1097 * object type field to be used in statements like CREATE TABLE. 1098 * 1099 * @param string $name name the field to be declared. 1100 * @param string $field associative array with the name of the properties 1101 * of the field being declared as array indexes. Currently, the types 1102 * of supported field properties are as follows: 1103 * 1104 * length 1105 * Integer value that determines the maximum length of the large 1106 * object field. If this argument is missing the field should be 1107 * declared to have the longest length allowed by the DBMS. 1108 * 1109 * notnull 1110 * Boolean flag that indicates whether this field is constrained 1111 * to not be set to NULL. 1112 * @return string DBMS specific SQL code portion that should be used to 1113 * declare the specified field. 1114 * @access public 1115 */ 1116 function getBlobDeclaration($name, $field) 1117 { 1118 return("$name BLOB".(isset($field['notnull']) ? ' NOT NULL' : '')); 1119 } 1120 1121 // }}} 1122 // {{{ getBooleanDeclaration() 1123 1124 /** 1125 * Obtain DBMS specific SQL code portion needed to declare a boolean type 1126 * field to be used in statements like CREATE TABLE. 1127 * 1128 * @param string $name name the field to be declared. 1129 * @param string $field associative array with the name of the properties 1130 * of the field being declared as array indexes. Currently, the types 1131 * of supported field properties are as follows: 1132 * 1133 * default 1134 * Boolean value to be used as default for this field. 1135 * 1136 * notnullL 1137 * Boolean flag that indicates whether this field is constrained 1138 * to not be set to NULL. 1139 * @return string DBMS specific SQL code portion that should be used to 1140 * declare the specified field. 1141 * @access public 1142 */ 1143 function getBooleanDeclaration($name, $field) 1144 { 1145 return("$name ".$this->getTypeDeclaration($field) 1146 .(isset($field['default']) ? ' DEFAULT ' 1147 .$this->getBooleanValue($field['default']) : '') 1148 .(isset($field['notnull']) ? ' NOT NULL' : '')); 1149 } 1150 1151 // }}} 1152 // {{{ getDateDeclaration() 1153 1154 /** 1155 * Obtain DBMS specific SQL code portion needed to declare a date type 1156 * field to be used in statements like CREATE TABLE. 1157 * 1158 * @param string $name name the field to be declared. 1159 * @param string $field associative array with the name of the properties 1160 * of the field being declared as array indexes. Currently, the types 1161 * of supported field properties are as follows: 1162 * 1163 * default 1164 * Date value to be used as default for this field. 1165 * 1166 * notnull 1167 * Boolean flag that indicates whether this field is constrained 1168 * to not be set to NULL. 1169 * @return string DBMS specific SQL code portion that should be used to 1170 * declare the specified field. 1171 * @access public 1172 */ 1173 function getDateDeclaration($name, $field) 1174 { 1175 return("$name ".$this->getTypeDeclaration($field) 1176 .(isset($field['default']) ? ' DEFAULT ' 1177 .$this->getDateValue($field['default']) : '') 1178 .(isset($field['notnull']) ? ' NOT NULL' : '')); 1179 } 1180 1181 // }}} 1182 // {{{ getTimestampDeclaration() 1183 1184 /** 1185 * Obtain DBMS specific SQL code portion needed to declare a timestamp 1186 * field to be used in statements like CREATE TABLE. 1187 * 1188 * @param string $name name the field to be declared. 1189 * @param string $field associative array with the name of the properties 1190 * of the field being declared as array indexes. Currently, the types 1191 * of supported field properties are as follows: 1192 * 1193 * default 1194 * Timestamp value to be used as default for this field. 1195 * 1196 * notnull 1197 * Boolean flag that indicates whether this field is constrained 1198 * to not be set to NULL. 1199 * @return string DBMS specific SQL code portion that should be used to 1200 * declare the specified field. 1201 * @access public 1202 */ 1203 function getTimestampDeclaration($name, $field) 1204 { 1205 return("$name ".$this->getTypeDeclaration($field) 1206 .(isset($field['default']) ? ' DEFAULT ' 1207 .$this->getTimestampValue($field['default']) : '') 1208 .(isset($field['notnull']) ? ' NOT NULL' : '')); 1209 } 1210 1211 // }}} 1212 // {{{ getTimeDeclaration() 1213 1214 /** 1215 * Obtain DBMS specific SQL code portion needed to declare a time 1216 * field to be used in statements like CREATE TABLE. 1217 * 1218 * @param string $name name the field to be declared. 1219 * @param string $field associative array with the name of the properties 1220 * of the field being declared as array indexes. Currently, the types 1221 * of supported field properties are as follows: 1222 * 1223 * default 1224 * Time value to be used as default for this field. 1225 * 1226 * notnull 1227 * Boolean flag that indicates whether this field is constrained 1228 * to not be set to NULL. 1229 * @return string DBMS specific SQL code portion that should be used to 1230 * declare the specified field. 1231 * @access public 1232 */ 1233 function getTimeDeclaration($name, $field) 1234 { 1235 return("$name ".$this->getTypeDeclaration($field) 1236 .(isset($field['default']) ? ' DEFAULT ' 1237 .$this->getTimeValue($field['default']) : '') 1238 .(isset($field['notnull']) ? ' NOT NULL' : '')); 1239 } 1240 1241 // }}} 1242 // {{{ getFloatDeclaration() 1243 1244 /** 1245 * Obtain DBMS specific SQL code portion needed to declare a float type 1246 * field to be used in statements like CREATE TABLE. 1247 * 1248 * @param string $name name the field to be declared. 1249 * @param string $field associative array with the name of the properties 1250 * of the field being declared as array indexes. Currently, the types 1251 * of supported field properties are as follows: 1252 * 1253 * default 1254 * Float value to be used as default for this field. 1255 * 1256 * notnull 1257 * Boolean flag that indicates whether this field is constrained 1258 * to not be set to NULL. 1259 * @return string DBMS specific SQL code portion that should be used to 1260 * declare the specified field. 1261 * @access public 1262 */ 1263 function getFloatDeclaration($name, $field) 1264 { 1265 return("$name ".$this->getTypeDeclaration($field) 1266 .(isset($field['default']) ? ' DEFAULT ' 1267 .$this->getFloatValue($field['default']) : '') 1268 .(isset($field['notnull']) ? ' NOT NULL' : '')); 1269 } 1270 1271 // }}} 1272 // {{{ getDecimalDeclaration() 1273 1274 /** 1275 * Obtain DBMS specific SQL code portion needed to declare a decimal type 1276 * field to be used in statements like CREATE TABLE. 1277 * 1278 * @param string $name name the field to be declared. 1279 * @param string $field associative array with the name of the properties 1280 * of the field being declared as array indexes. Currently, the types 1281 * of supported field properties are as follows: 1282 * 1283 * default 1284 * Decimal value to be used as default for this field. 1285 * 1286 * notnull 1287 * Boolean flag that indicates whether this field is constrained 1288 * to not be set to NULL. 1289 * @return string DBMS specific SQL code portion that should be used to 1290 * declare the specified field. 1291 * @access public 1292 */ 1293 function getDecimalDeclaration($name, $field) 1294 { 1295 return("$name ".$this->getTypeDeclaration($field) 1296 .(isset($field['default']) ? ' DEFAULT ' 1297 .$this->getDecimalValue($field['default']) : '') 1298 .(isset($field['notnull']) ? ' NOT NULL' : '')); 1299 } 1300 1301 // }}} 1302 // {{{ getClobValue() 1303 1304 /** 1305 * Convert a text value into a DBMS specific format that is suitable to 1306 * compose query statements. 1307 * 1308 * @param resource $prepared_query query handle from prepare() 1309 * @param $parameter 1310 * @param $clob 1311 * @return string text string that represents the given argument value in 1312 * a DBMS specific format. 1313 * @access public 1314 */ 1315 function getClobValue($prepared_query, $parameter, $clob) 1316 { 1317 return('EMPTY_CLOB()'); 1318 } 1319 1320 // }}} 1321 // {{{ freeClobValue() 1322 1323 /** 1324 * free a character large object 1325 * 1326 * @param resource $prepared_query query handle from prepare() 1327 * @param string $blob 1328 * @param string $value 1329 * @access public 1330 */ 1331 function freeClobValue($prepared_query, $clob, &$value) 1332 { 1333 unset($value); 1334 } 1335 1336 // }}} 1337 // {{{ getBlobValue() 1338 1339 /** 1340 * Convert a text value into a DBMS specific format that is suitable to 1341 * compose query statements. 1342 * 1343 * @param resource $prepared_query query handle from prepare() 1344 * @param $parameter 1345 * @param $blob 1346 * @return string text string that represents the given argument value in 1347 * a DBMS specific format. 1348 * @access public 1349 */ 1350 function getBlobValue($prepared_query, $parameter, $blob) 1351 { 1352 return('EMPTY_BLOB()'); 1353 } 1354 1355 // }}} 1356 // {{{ freeBlobValue() 1357 1358 /** 1359 * free a binary large object 1360 * 1361 * @param resource $prepared_query query handle from prepare() 1362 * @param string $blob 1363 * @param string $value 1364 * @access public 1365 */ 1366 function freeBlobValue($prepared_query, $blob, &$value) 1367 { 1368 unset($value); 1369 } 1370 1371 // }}} 1372 // {{{ getDateValue() 1373 1374 /** 1375 * Convert a text value into a DBMS specific format that is suitable to 1376 * compose query statements. 1377 * 1378 * @param string $value text string value that is intended to be converted. 1379 * @return string text string that represents the given argument value in 1380 * a DBMS specific format. 1381 * @access public 1382 */ 1383 function getDateValue($value) 1384 { 1385 return(($value === NULL) ? 'NULL' : "TO_DATE('$value','YYYY-MM-DD')"); 1386 } 1387 1388 // }}} 1389 // {{{ getTimestampValue() 1390 1391 /** 1392 * Convert a text value into a DBMS specific format that is suitable to 1393 * compose query statements. 1394 * 1395 * @param string $value text string value that is intended to be converted. 1396 * @return string text string that represents the given argument value in 1397 * a DBMS specific format. 1398 * @access public 1399 */ 1400 function getTimestampValue($value) 1401 { 1402 return(($value === NULL) ? 'NULL' : "TO_DATE('$value','YYYY-MM-DD HH24:MI:SS')"); 1403 } 1404 1405 // }}} 1406 // {{{ getTimeValue() 1407 1408 /** 1409 * Convert a text value into a DBMS specific format that is suitable to 1410 * compose query statements. 1411 * 1412 * @param string $value text string value that is intended to be converted. 1413 * @return string text string that represents the given argument value in 1414 * a DBMS specific format. 1415 * @access public 1416 */ 1417 function getTimeValue($value) 1418 { 1419 return(($value === NULL) ? 'NULL' : "TO_DATE('0001-01-01 $value','YYYY-MM-DD HH24:MI:SS')"); 1420 } 1421 1422 // }}} 1423 // {{{ getFloatValue() 1424 1425 /** 1426 * Convert a text value into a DBMS specific format that is suitable to 1427 * compose query statements. 1428 * 1429 * @param string $value text string value that is intended to be converted. 1430 * @return string text string that represents the given argument value in 1431 * a DBMS specific format. 1432 * @access public 1433 */ 1434 function getFloatValue($value) 1435 { 1436 return(($value === NULL) ? 'NULL' : (float)$value); 1437 } 1438 1439 // }}} 1440 // {{{ getDecimalValue() 1441 1442 /** 1443 * Convert a text value into a DBMS specific format that is suitable to 1444 * compose query statements. 1445 * 1446 * @param string $value text string value that is intended to be converted. 1447 * @return string text string that represents the given argument value in 1448 * a DBMS specific format. 1449 * @access public 1450 */ 1451 function getDecimalValue($value) 1452 { 1453 return(($value === NULL) ? 'NULL' : $value); 1454 } 1455 1456 // }}} 1457 // {{{ nextId() 1458 1459 /** 1460 * returns the next free id of a sequence 1461 * 1462 * @param string $seq_name name of the sequence 1463 * @param boolean $ondemand when TRUE the seqence is 1464 * automatic created, if it 1465 * not exists 1466 * @return mixed MDB_Error or id 1467 * @access public 1468 */ 1469 function nextId($seq_name, $ondemand = TRUE) 1470 { 1471 if (MDB::isError($connect = $this->connect())) { 1472 return($connect); 1473 } 1474 $sequence_name = $this->getSequenceName($seq_name); 1475 $this->expectError(MDB_ERROR_NOSUCHTABLE); 1476 $result = $this->_doQuery("SELECT $sequence_name.nextval FROM DUAL"); 1477 $this->popExpect(); 1478 if ($ondemand && MDB::isError($result) 1479 && $result->getCode() == MDB_ERROR_NOSUCHTABLE) 1480 { 1481 $result = $this->createSequence($seq_name, 1); 1482 if (MDB::isError($result)) { 1483 return $result; 1484 } 1485 return $this->nextId($seq_name, false); 1486 } 1487 return($this->fetchOne($result)); 1488 } 1489 1490 // }}} 1491 // {{{ currId() 1492 1493 /** 1494 * returns the current id of a sequence 1495 * 1496 * @param string $seq_name name of the sequence 1497 * @return mixed MDB_Error or id 1498 * @access public 1499 */ 1500 function currId($seq_name) 1501 { 1502 $sequence_name = $this->getSequenceName($seq_name); 1503 $result = $this->_doQuery("SELECT $sequence_name.currval FROM DUAL"); 1504 if (MDB::isError($result)) { 1505 return($this->raiseError(MDB_ERROR, NULL, NULL, 1506 'currId: unable to select from ' . $seq_name) ); 1507 } 1508 $result = $this->fetchOne($result); 1509 if (!is_numeric($result)) { 1510 return($this->raiseError(MDB_ERROR, NULL, NULL, 1511 'currId: could not find value in sequence table')); 1512 } 1513 return($result); 1514 } 1515 1516 // }}} 1517 // {{{ fetchInto() 1518 1519 /** 1520 * Fetch a row and return data in an array. 1521 * 1522 * @param resource $result result identifier 1523 * @param int $fetchmode how the array data should be indexed 1524 * @param int $rownum the row number to fetch 1525 * @return mixed data array or NULL on success, a MDB error on failure 1526 * @access public 1527 */ 1528 function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL) 1529 { 1530 $result_value = intval($result); 1531 if (!isset($this->current_row[$result_value])) { 1532 return($this->raiseError(MDB_ERROR, NULL, NULL, 1533 'fetchInto: attemped to fetch on an unknown query result')); 1534 } 1535 if ($fetchmode == MDB_FETCHMODE_DEFAULT) { 1536 $fetchmode = $this->fetchmode; 1537 } 1538 if (is_null($rownum)) { 1539 $rownum = $this->current_row[$result_value] + 1; 1540 } 1541 if (!isset($this->results[$result_value][$rownum]) 1542 && (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]]) 1543 || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== FALSE) 1544 ) { 1545 if (isset($this->limits[$result_value])) { 1546 // upper limit 1547 if ($rownum > $this->limits[$result_value][1]) { 1548 // are all previous rows fetched so that we can set the end 1549 // of the result set and not have any "holes" in between? 1550 if ($rownum == 0 1551 || (isset($this->results[$result_value]) 1552 && count($this->results[$result_value]) == $rownum 1553 ) 1554 ) { 1555 $this->highest_fetched_row[$result_value] = $rownum; 1556 $this->current_row[$result_value] = $rownum; 1557 $this->results[$result_value][$rownum] = FALSE; 1558 } 1559 if($this->options['autofree']) { 1560 $this->freeResult($result); 1561 } 1562 return(NULL); 1563 } 1564 // offset skipping 1565 if (MDB::isError($this->_skipLimitOffset($result))) { 1566 $this->current_row[$result_value] = 0; 1567 $this->results[$result_value] = array(FALSE); 1568 if($this->options['autofree']) { 1569 $this->freeResult($result); 1570 } 1571 return(NULL); 1572 } 1573 } 1574 if (isset($this->row_buffer[$result_value])) { 1575 ++$this->current_row[$result_value]; 1576 $this->results[$result_value][$this->current_row[$result_value]] = 1577 $this->row_buffer[$result_value]; 1578 unset($this->row_buffer[$result_value]); 1579 } 1580 if (!isset($this->results[$result_value][$rownum]) 1581 && (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]]) 1582 || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== FALSE) 1583 ) { 1584 while($this->current_row[$result_value] < $rownum 1585 && @OCIFetchInto($result, $buffer, OCI_RETURN_NULLS) 1586 ) { 1587 ++$this->current_row[$result_value]; 1588 $this->results[$result_value][$this->current_row[$result_value]] = $buffer; 1589 } 1590 // end of result set reached 1591 if ($this->current_row[$result_value] < $rownum) { 1592 ++$this->current_row[$result_value]; 1593 $this->results[$result_value][$this->current_row[$result_value]] = FALSE; 1594 } 1595 } 1596 $this->highest_fetched_row[$result_value] = 1597 max($this->highest_fetched_row[$result_value], 1598 $this->current_row[$result_value]); 1599 } else { 1600 ++$this->current_row[$result_value]; 1601 } 1602 if (isset($this->results[$result_value][$rownum]) 1603 && $this->results[$result_value][$rownum] 1604 ) { 1605 $row = $this->results[$result_value][$rownum]; 1606 } else { 1607 if($this->options['autofree']) { 1608 $this->freeResult($result); 1609 } 1610 return(NULL); 1611 } 1612 if ($fetchmode & MDB_FETCHMODE_ASSOC) { 1613 $column_names = $this->getColumnNames($result); 1614 foreach($column_names as $name => $i) { 1615 $column_names[$name] = $row[$i]; 1616 } 1617 $row = $column_names; 1618 } 1619 if (isset($this->result_types[$result_value])) { 1620 $row = $this->convertResultRow($result, $row); 1621 } 1622 return($row); 1623 } 1624 1625 // }}} 1626 // {{{ nextResult() 1627 1628 /** 1629 * Move the internal oracle result pointer to the next available result 1630 * Currently not supported 1631 * 1632 * @param $result a oracle valid result resource 1633 * @return TRUE if a result is available otherwise return FALSE 1634 * @access public 1635 */ 1636 function nextResult($result) 1637 { 1638 return(FALSE); 1639 } 1640 1641 // }}} 1642 // {{{ tableInfo() 1643 1644 /** 1645 * returns meta data about the result set 1646 * 1647 * @param resource $result result identifier 1648 * @param mixed $mode depends on implementation 1649 * @return array an nested array, or a MDB error 1650 * @access public 1651 */ 1652 function tableInfo($result, $mode = NULL) 1653 { 1654 $count = 0; 1655 $res = array(); 1656 /** 1657 * depending on $mode, metadata returns the following values: 1658 * 1659 * - mode is FALSE (default): 1660 * $res[]: 1661 * [0]['table'] table name 1662 * [0]['name'] field name 1663 * [0]['type'] field type 1664 * [0]['len'] field length 1665 * [0]['nullable'] field can be NULL (boolean) 1666 * [0]['format'] field precision if NUMBER 1667 * [0]['default'] field default value 1668 * 1669 * - mode is MDB_TABLEINFO_ORDER 1670 * $res[]: 1671 * ['num_fields'] number of fields 1672 * [0]['table'] table name 1673 * [0]['name'] field name 1674 * [0]['type'] field type 1675 * [0]['len'] field length 1676 * [0]['nullable'] field can be NULL (boolean) 1677 * [0]['format'] field precision if NUMBER 1678 * [0]['default'] field default value 1679 * ['order'][field name] index of field named 'field name' 1680 * The last one is used, if you have a field name, but no index. 1681 * Test: if (isset($result['order']['myfield'])) { ... 1682 * 1683 * - mode is MDB_TABLEINFO_ORDERTABLE 1684 * the same as above. but additionally 1685 * ['ordertable'][table name][field name] index of field 1686 * named 'field name' 1687 * 1688 * this is, because if you have fields from different 1689 * tables with the same field name * they override each 1690 * other with MDB_TABLEINFO_ORDER 1691 * 1692 * you can combine DB_TABLEINFO_ORDER and 1693 * MDB_TABLEINFO_ORDERTABLE with MDB_TABLEINFO_ORDER | 1694 * MDB_TABLEINFO_ORDERTABLE * or with MDB_TABLEINFO_FULL 1695 */ 1696 // if $result is a string, we collect info for a table only 1697 if (is_string($result)) { 1698 if (MDB::isError($connect = $this->connect())) { 1699 return($connect); 1700 } 1701 $result = strtoupper($result); 1702 $q_fields = "select column_name, data_type, data_length, data_precision, 1703 nullable, data_default from user_tab_columns 1704 where table_name='$result' order by column_id"; 1705 if (!$stmt = @OCIParse($this->connection, $q_fields)) { 1706 return($this->oci8RaiseError()); 1707 } 1708 if (!@OCIExecute($stmt, OCI_DEFAULT)) { 1709 return($this->oci8RaiseError($stmt)); 1710 } while (@OCIFetch($stmt)) { 1711 $res[$count]['table'] = strtolower($result); 1712 $res[$count]['name'] = strtolower(@OCIResult($stmt, 1)); 1713 $res[$count]['type'] = strtolower(@OCIResult($stmt, 2)); 1714 $res[$count]['len'] = @OCIResult($stmt, 3); 1715 $res[$count]['format'] = @OCIResult($stmt, 4); 1716 $res[$count]['nullable'] = (@OCIResult($stmt, 5) == 'Y') ? TRUE : FALSE; 1717 $res[$count]['default'] = @OCIResult($stmt, 6); 1718 if ($mode & MDB_TABLEINFO_ORDER) { 1719 $res['order'][$res[$count]['name']] = $count; 1720 } 1721 if ($mode & MDB_TABLEINFO_ORDERTABLE) { 1722 $res['ordertable'][$res[$count]['table']][$res[$count]['name']] = $count; 1723 } 1724 $count++; 1725 } 1726 if ($mode) { 1727 $res['num_fields'] = $count; 1728 } 1729 @OCIFreeStatement($stmt); 1730 } else { // else we want information about a resultset 1731 #if ($result === $this->last_stmt) { 1732 $count = @OCINumCols($result); 1733 for ($i = 0; $i < $count; $i++) { 1734 $res[$i]['name'] = strtolower(@OCIColumnName($result, $i + 1)); 1735 $res[$i]['type'] = strtolower(@OCIColumnType($result, $i + 1)); 1736 $res[$i]['len'] = @OCIColumnSize($result, $i + 1); 1737 1738 $q_fields = "SELECT table_name, data_precision, nullable, data_default from user_tab_columns WHERE column_name='".$res[$i]['name']."'"; 1739 if (!$stmt = @OCIParse($this->connection, $q_fields)) { 1740 return($this->oci8RaiseError()); 1741 } 1742 if (!@OCIExecute($stmt, OCI_DEFAULT)) { 1743 return($this->oci8RaiseError($stmt)); 1744 } 1745 @OCIFetch($stmt); 1746 $res[$i]['table'] = strtolower(@OCIResult($stmt, 1)); 1747 $res[$i]['format'] = @OCIResult($stmt, 2); 1748 $res[$i]['nullable'] = (@OCIResult($stmt, 3) == 'Y') ? TRUE : FALSE; 1749 $res[$i]['default'] = @OCIResult($stmt, 4); 1750 @OCIFreeStatement($stmt); 1751 1752 if ($mode & MDB_TABLEINFO_ORDER) { 1753 $res['order'][$res[$i]['name']] = $i; 1754 } 1755 if ($mode & MDB_TABLEINFO_ORDERTABLE) { 1756 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 1757 } 1758 } 1759 if ($mode) { 1760 $res['num_fields'] = $count; 1761 } 1762 #} else { 1763 # return($this->raiseError(MDB_ERROR_NOT_CAPABLE)); 1764 #} 1765 } 1766 return($res); 1767 } 1768 } 1769 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sun Feb 25 14:08:00 2007 | par Balluche grâce à PHPXref 0.7 |