| [ Index ] |
|
Code source de PHP PEAR 1.4.5 |
1 <?php 2 3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 4 5 /** 6 * The PEAR DB driver for PHP's interbase extension 7 * for interacting with Interbase and Firebird databases 8 * 9 * While this class works with PHP 4, PHP's InterBase extension is 10 * unstable in PHP 4. Use PHP 5. 11 * 12 * PHP versions 4 and 5 13 * 14 * LICENSE: This source file is subject to version 3.0 of the PHP license 15 * that is available through the world-wide-web at the following URI: 16 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 17 * the PHP License and are unable to obtain it through the web, please 18 * send a note to license@php.net so we can mail you a copy immediately. 19 * 20 * @category Database 21 * @package DB 22 * @author Sterling Hughes <sterling@php.net> 23 * @author Daniel Convissor <danielc@php.net> 24 * @copyright 1997-2005 The PHP Group 25 * @license http://www.php.net/license/3_0.txt PHP License 3.0 26 * @version CVS: $Id: ibase.php,v 1.113 2007/01/12 03:11:17 aharvey Exp $ 27 * @link http://pear.php.net/package/DB 28 */ 29 30 /** 31 * Obtain the DB_common class so it can be extended from 32 */ 33 require_once 'DB/common.php'; 34 35 /** 36 * The methods PEAR DB uses to interact with PHP's interbase extension 37 * for interacting with Interbase and Firebird databases 38 * 39 * These methods overload the ones declared in DB_common. 40 * 41 * While this class works with PHP 4, PHP's InterBase extension is 42 * unstable in PHP 4. Use PHP 5. 43 * 44 * NOTICE: limitQuery() only works for Firebird. 45 * 46 * @category Database 47 * @package DB 48 * @author Sterling Hughes <sterling@php.net> 49 * @author Daniel Convissor <danielc@php.net> 50 * @copyright 1997-2005 The PHP Group 51 * @license http://www.php.net/license/3_0.txt PHP License 3.0 52 * @version Release: 1.7.9 53 * @link http://pear.php.net/package/DB 54 * @since Class became stable in Release 1.7.0 55 */ 56 class DB_ibase extends DB_common 57 { 58 // {{{ properties 59 60 /** 61 * The DB driver type (mysql, oci8, odbc, etc.) 62 * @var string 63 */ 64 var $phptype = 'ibase'; 65 66 /** 67 * The database syntax variant to be used (db2, access, etc.), if any 68 * @var string 69 */ 70 var $dbsyntax = 'ibase'; 71 72 /** 73 * The capabilities of this DB implementation 74 * 75 * The 'new_link' element contains the PHP version that first provided 76 * new_link support for this DBMS. Contains false if it's unsupported. 77 * 78 * Meaning of the 'limit' element: 79 * + 'emulate' = emulate with fetch row by number 80 * + 'alter' = alter the query 81 * + false = skip rows 82 * 83 * NOTE: only firebird supports limit. 84 * 85 * @var array 86 */ 87 var $features = array( 88 'limit' => false, 89 'new_link' => false, 90 'numrows' => 'emulate', 91 'pconnect' => true, 92 'prepare' => true, 93 'ssl' => false, 94 'transactions' => true, 95 ); 96 97 /** 98 * A mapping of native error codes to DB error codes 99 * @var array 100 */ 101 var $errorcode_map = array( 102 -104 => DB_ERROR_SYNTAX, 103 -150 => DB_ERROR_ACCESS_VIOLATION, 104 -151 => DB_ERROR_ACCESS_VIOLATION, 105 -155 => DB_ERROR_NOSUCHTABLE, 106 -157 => DB_ERROR_NOSUCHFIELD, 107 -158 => DB_ERROR_VALUE_COUNT_ON_ROW, 108 -170 => DB_ERROR_MISMATCH, 109 -171 => DB_ERROR_MISMATCH, 110 -172 => DB_ERROR_INVALID, 111 // -204 => // Covers too many errors, need to use regex on msg 112 -205 => DB_ERROR_NOSUCHFIELD, 113 -206 => DB_ERROR_NOSUCHFIELD, 114 -208 => DB_ERROR_INVALID, 115 -219 => DB_ERROR_NOSUCHTABLE, 116 -297 => DB_ERROR_CONSTRAINT, 117 -303 => DB_ERROR_INVALID, 118 -413 => DB_ERROR_INVALID_NUMBER, 119 -530 => DB_ERROR_CONSTRAINT, 120 -551 => DB_ERROR_ACCESS_VIOLATION, 121 -552 => DB_ERROR_ACCESS_VIOLATION, 122 // -607 => // Covers too many errors, need to use regex on msg 123 -625 => DB_ERROR_CONSTRAINT_NOT_NULL, 124 -803 => DB_ERROR_CONSTRAINT, 125 -804 => DB_ERROR_VALUE_COUNT_ON_ROW, 126 // -902 => // Covers too many errors, need to use regex on msg 127 -904 => DB_ERROR_CONNECT_FAILED, 128 -922 => DB_ERROR_NOSUCHDB, 129 -923 => DB_ERROR_CONNECT_FAILED, 130 -924 => DB_ERROR_CONNECT_FAILED 131 ); 132 133 /** 134 * The raw database connection created by PHP 135 * @var resource 136 */ 137 var $connection; 138 139 /** 140 * The DSN information for connecting to a database 141 * @var array 142 */ 143 var $dsn = array(); 144 145 146 /** 147 * The number of rows affected by a data manipulation query 148 * @var integer 149 * @access private 150 */ 151 var $affected = 0; 152 153 /** 154 * Should data manipulation queries be committed automatically? 155 * @var bool 156 * @access private 157 */ 158 var $autocommit = true; 159 160 /** 161 * The prepared statement handle from the most recently executed statement 162 * 163 * {@internal Mainly here because the InterBase/Firebird API is only 164 * able to retrieve data from result sets if the statemnt handle is 165 * still in scope.}} 166 * 167 * @var resource 168 */ 169 var $last_stmt; 170 171 /** 172 * Is the given prepared statement a data manipulation query? 173 * @var array 174 * @access private 175 */ 176 var $manip_query = array(); 177 178 179 // }}} 180 // {{{ constructor 181 182 /** 183 * This constructor calls <kbd>$this->DB_common()</kbd> 184 * 185 * @return void 186 */ 187 function DB_ibase() 188 { 189 $this->DB_common(); 190 } 191 192 // }}} 193 // {{{ connect() 194 195 /** 196 * Connect to the database server, log in and open the database 197 * 198 * Don't call this method directly. Use DB::connect() instead. 199 * 200 * PEAR DB's ibase driver supports the following extra DSN options: 201 * + buffers The number of database buffers to allocate for the 202 * server-side cache. 203 * + charset The default character set for a database. 204 * + dialect The default SQL dialect for any statement 205 * executed within a connection. Defaults to the 206 * highest one supported by client libraries. 207 * Functional only with InterBase 6 and up. 208 * + role Functional only with InterBase 5 and up. 209 * 210 * @param array $dsn the data source name 211 * @param bool $persistent should the connection be persistent? 212 * 213 * @return int DB_OK on success. A DB_Error object on failure. 214 */ 215 function connect($dsn, $persistent = false) 216 { 217 if (!PEAR::loadExtension('interbase')) { 218 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 219 } 220 221 $this->dsn = $dsn; 222 if ($dsn['dbsyntax']) { 223 $this->dbsyntax = $dsn['dbsyntax']; 224 } 225 if ($this->dbsyntax == 'firebird') { 226 $this->features['limit'] = 'alter'; 227 } 228 229 $params = array( 230 $dsn['hostspec'] 231 ? ($dsn['hostspec'] . ':' . $dsn['database']) 232 : $dsn['database'], 233 $dsn['username'] ? $dsn['username'] : null, 234 $dsn['password'] ? $dsn['password'] : null, 235 isset($dsn['charset']) ? $dsn['charset'] : null, 236 isset($dsn['buffers']) ? $dsn['buffers'] : null, 237 isset($dsn['dialect']) ? $dsn['dialect'] : null, 238 isset($dsn['role']) ? $dsn['role'] : null, 239 ); 240 241 $connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect'; 242 243 $this->connection = @call_user_func_array($connect_function, $params); 244 if (!$this->connection) { 245 return $this->ibaseRaiseError(DB_ERROR_CONNECT_FAILED); 246 } 247 return DB_OK; 248 } 249 250 // }}} 251 // {{{ disconnect() 252 253 /** 254 * Disconnects from the database server 255 * 256 * @return bool TRUE on success, FALSE on failure 257 */ 258 function disconnect() 259 { 260 $ret = @ibase_close($this->connection); 261 $this->connection = null; 262 return $ret; 263 } 264 265 // }}} 266 // {{{ simpleQuery() 267 268 /** 269 * Sends a query to the database server 270 * 271 * @param string the SQL query string 272 * 273 * @return mixed + a PHP result resrouce for successful SELECT queries 274 * + the DB_OK constant for other successful queries 275 * + a DB_Error object on failure 276 */ 277 function simpleQuery($query) 278 { 279 $ismanip = $this->_checkManip($query); 280 $this->last_query = $query; 281 $query = $this->modifyQuery($query); 282 $result = @ibase_query($this->connection, $query); 283 284 if (!$result) { 285 return $this->ibaseRaiseError(); 286 } 287 if ($this->autocommit && $ismanip) { 288 @ibase_commit($this->connection); 289 } 290 if ($ismanip) { 291 $this->affected = $result; 292 return DB_OK; 293 } else { 294 $this->affected = 0; 295 return $result; 296 } 297 } 298 299 // }}} 300 // {{{ modifyLimitQuery() 301 302 /** 303 * Adds LIMIT clauses to a query string according to current DBMS standards 304 * 305 * Only works with Firebird. 306 * 307 * @param string $query the query to modify 308 * @param int $from the row to start to fetching (0 = the first row) 309 * @param int $count the numbers of rows to fetch 310 * @param mixed $params array, string or numeric data to be used in 311 * execution of the statement. Quantity of items 312 * passed must match quantity of placeholders in 313 * query: meaning 1 placeholder for non-array 314 * parameters or 1 placeholder per array element. 315 * 316 * @return string the query string with LIMIT clauses added 317 * 318 * @access protected 319 */ 320 function modifyLimitQuery($query, $from, $count, $params = array()) 321 { 322 if ($this->dsn['dbsyntax'] == 'firebird') { 323 $query = preg_replace('/^([\s(])*SELECT/i', 324 "SELECT FIRST $count SKIP $from", $query); 325 } 326 return $query; 327 } 328 329 // }}} 330 // {{{ nextResult() 331 332 /** 333 * Move the internal ibase result pointer to the next available result 334 * 335 * @param a valid fbsql result resource 336 * 337 * @access public 338 * 339 * @return true if a result is available otherwise return false 340 */ 341 function nextResult($result) 342 { 343 return false; 344 } 345 346 // }}} 347 // {{{ fetchInto() 348 349 /** 350 * Places a row from the result set into the given array 351 * 352 * Formating of the array and the data therein are configurable. 353 * See DB_result::fetchInto() for more information. 354 * 355 * This method is not meant to be called directly. Use 356 * DB_result::fetchInto() instead. It can't be declared "protected" 357 * because DB_result is a separate object. 358 * 359 * @param resource $result the query result resource 360 * @param array $arr the referenced array to put the data in 361 * @param int $fetchmode how the resulting array should be indexed 362 * @param int $rownum the row number to fetch (0 = first row) 363 * 364 * @return mixed DB_OK on success, NULL when the end of a result set is 365 * reached or on failure 366 * 367 * @see DB_result::fetchInto() 368 */ 369 function fetchInto($result, &$arr, $fetchmode, $rownum = null) 370 { 371 if ($rownum !== null) { 372 return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE); 373 } 374 if ($fetchmode & DB_FETCHMODE_ASSOC) { 375 if (function_exists('ibase_fetch_assoc')) { 376 $arr = @ibase_fetch_assoc($result); 377 } else { 378 $arr = get_object_vars(ibase_fetch_object($result)); 379 } 380 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { 381 $arr = array_change_key_case($arr, CASE_LOWER); 382 } 383 } else { 384 $arr = @ibase_fetch_row($result); 385 } 386 if (!$arr) { 387 return null; 388 } 389 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 390 $this->_rtrimArrayValues($arr); 391 } 392 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 393 $this->_convertNullArrayValuesToEmpty($arr); 394 } 395 return DB_OK; 396 } 397 398 // }}} 399 // {{{ freeResult() 400 401 /** 402 * Deletes the result set and frees the memory occupied by the result set 403 * 404 * This method is not meant to be called directly. Use 405 * DB_result::free() instead. It can't be declared "protected" 406 * because DB_result is a separate object. 407 * 408 * @param resource $result PHP's query result resource 409 * 410 * @return bool TRUE on success, FALSE if $result is invalid 411 * 412 * @see DB_result::free() 413 */ 414 function freeResult($result) 415 { 416 return is_resource($result) ? ibase_free_result($result) : false; 417 } 418 419 // }}} 420 // {{{ freeQuery() 421 422 function freeQuery($query) 423 { 424 return is_resource($query) ? ibase_free_query($query) : false; 425 } 426 427 // }}} 428 // {{{ affectedRows() 429 430 /** 431 * Determines the number of rows affected by a data maniuplation query 432 * 433 * 0 is returned for queries that don't manipulate data. 434 * 435 * @return int the number of rows. A DB_Error object on failure. 436 */ 437 function affectedRows() 438 { 439 if (is_integer($this->affected)) { 440 return $this->affected; 441 } 442 return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE); 443 } 444 445 // }}} 446 // {{{ numCols() 447 448 /** 449 * Gets the number of columns in a result set 450 * 451 * This method is not meant to be called directly. Use 452 * DB_result::numCols() instead. It can't be declared "protected" 453 * because DB_result is a separate object. 454 * 455 * @param resource $result PHP's query result resource 456 * 457 * @return int the number of columns. A DB_Error object on failure. 458 * 459 * @see DB_result::numCols() 460 */ 461 function numCols($result) 462 { 463 $cols = @ibase_num_fields($result); 464 if (!$cols) { 465 return $this->ibaseRaiseError(); 466 } 467 return $cols; 468 } 469 470 // }}} 471 // {{{ prepare() 472 473 /** 474 * Prepares a query for multiple execution with execute(). 475 * 476 * prepare() requires a generic query as string like <code> 477 * INSERT INTO numbers VALUES (?, ?, ?) 478 * </code>. The <kbd>?</kbd> characters are placeholders. 479 * 480 * Three types of placeholders can be used: 481 * + <kbd>?</kbd> a quoted scalar value, i.e. strings, integers 482 * + <kbd>!</kbd> value is inserted 'as is' 483 * + <kbd>&</kbd> requires a file name. The file's contents get 484 * inserted into the query (i.e. saving binary 485 * data in a db) 486 * 487 * Use backslashes to escape placeholder characters if you don't want 488 * them to be interpreted as placeholders. Example: <code> 489 * "UPDATE foo SET col=? WHERE col='over \& under'" 490 * </code> 491 * 492 * @param string $query query to be prepared 493 * @return mixed DB statement resource on success. DB_Error on failure. 494 */ 495 function prepare($query) 496 { 497 $tokens = preg_split('/((?<!\\\)[&?!])/', $query, -1, 498 PREG_SPLIT_DELIM_CAPTURE); 499 $token = 0; 500 $types = array(); 501 $newquery = ''; 502 503 foreach ($tokens as $key => $val) { 504 switch ($val) { 505 case '?': 506 $types[$token++] = DB_PARAM_SCALAR; 507 break; 508 case '&': 509 $types[$token++] = DB_PARAM_OPAQUE; 510 break; 511 case '!': 512 $types[$token++] = DB_PARAM_MISC; 513 break; 514 default: 515 $tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val); 516 $newquery .= $tokens[$key] . '?'; 517 } 518 } 519 520 $newquery = substr($newquery, 0, -1); 521 $this->last_query = $query; 522 $newquery = $this->modifyQuery($newquery); 523 $stmt = @ibase_prepare($this->connection, $newquery); 524 525 if ($stmt === false) { 526 $stmt = $this->ibaseRaiseError(); 527 } else { 528 $this->prepare_types[(int)$stmt] = $types; 529 $this->manip_query[(int)$stmt] = DB::isManip($query); 530 } 531 532 return $stmt; 533 } 534 535 // }}} 536 // {{{ execute() 537 538 /** 539 * Executes a DB statement prepared with prepare(). 540 * 541 * @param resource $stmt a DB statement resource returned from prepare() 542 * @param mixed $data array, string or numeric data to be used in 543 * execution of the statement. Quantity of items 544 * passed must match quantity of placeholders in 545 * query: meaning 1 for non-array items or the 546 * quantity of elements in the array. 547 * @return object a new DB_Result or a DB_Error when fail 548 * @see DB_ibase::prepare() 549 * @access public 550 */ 551 function &execute($stmt, $data = array()) 552 { 553 $data = (array)$data; 554 $this->last_parameters = $data; 555 556 $types =& $this->prepare_types[(int)$stmt]; 557 if (count($types) != count($data)) { 558 $tmp =& $this->raiseError(DB_ERROR_MISMATCH); 559 return $tmp; 560 } 561 562 $i = 0; 563 foreach ($data as $key => $value) { 564 if ($types[$i] == DB_PARAM_MISC) { 565 /* 566 * ibase doesn't seem to have the ability to pass a 567 * parameter along unchanged, so strip off quotes from start 568 * and end, plus turn two single quotes to one single quote, 569 * in order to avoid the quotes getting escaped by 570 * ibase and ending up in the database. 571 */ 572 $data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]); 573 $data[$key] = str_replace("''", "'", $data[$key]); 574 } elseif ($types[$i] == DB_PARAM_OPAQUE) { 575 $fp = @fopen($data[$key], 'rb'); 576 if (!$fp) { 577 $tmp =& $this->raiseError(DB_ERROR_ACCESS_VIOLATION); 578 return $tmp; 579 } 580 $data[$key] = fread($fp, filesize($data[$key])); 581 fclose($fp); 582 } 583 $i++; 584 } 585 586 array_unshift($data, $stmt); 587 588 $res = call_user_func_array('ibase_execute', $data); 589 if (!$res) { 590 $tmp =& $this->ibaseRaiseError(); 591 return $tmp; 592 } 593 /* XXX need this? 594 if ($this->autocommit && $this->manip_query[(int)$stmt]) { 595 @ibase_commit($this->connection); 596 }*/ 597 $this->last_stmt = $stmt; 598 if ($this->manip_query[(int)$stmt] || $this->_next_query_manip) { 599 $this->_last_query_manip = true; 600 $this->_next_query_manip = false; 601 $tmp = DB_OK; 602 } else { 603 $this->_last_query_manip = false; 604 $tmp =& new DB_result($this, $res); 605 } 606 return $tmp; 607 } 608 609 /** 610 * Frees the internal resources associated with a prepared query 611 * 612 * @param resource $stmt the prepared statement's PHP resource 613 * @param bool $free_resource should the PHP resource be freed too? 614 * Use false if you need to get data 615 * from the result set later. 616 * 617 * @return bool TRUE on success, FALSE if $result is invalid 618 * 619 * @see DB_ibase::prepare() 620 */ 621 function freePrepared($stmt, $free_resource = true) 622 { 623 if (!is_resource($stmt)) { 624 return false; 625 } 626 if ($free_resource) { 627 @ibase_free_query($stmt); 628 } 629 unset($this->prepare_tokens[(int)$stmt]); 630 unset($this->prepare_types[(int)$stmt]); 631 unset($this->manip_query[(int)$stmt]); 632 return true; 633 } 634 635 // }}} 636 // {{{ autoCommit() 637 638 /** 639 * Enables or disables automatic commits 640 * 641 * @param bool $onoff true turns it on, false turns it off 642 * 643 * @return int DB_OK on success. A DB_Error object if the driver 644 * doesn't support auto-committing transactions. 645 */ 646 function autoCommit($onoff = false) 647 { 648 $this->autocommit = $onoff ? 1 : 0; 649 return DB_OK; 650 } 651 652 // }}} 653 // {{{ commit() 654 655 /** 656 * Commits the current transaction 657 * 658 * @return int DB_OK on success. A DB_Error object on failure. 659 */ 660 function commit() 661 { 662 return @ibase_commit($this->connection); 663 } 664 665 // }}} 666 // {{{ rollback() 667 668 /** 669 * Reverts the current transaction 670 * 671 * @return int DB_OK on success. A DB_Error object on failure. 672 */ 673 function rollback() 674 { 675 return @ibase_rollback($this->connection); 676 } 677 678 // }}} 679 // {{{ transactionInit() 680 681 function transactionInit($trans_args = 0) 682 { 683 return $trans_args 684 ? @ibase_trans($trans_args, $this->connection) 685 : @ibase_trans(); 686 } 687 688 // }}} 689 // {{{ nextId() 690 691 /** 692 * Returns the next free id in a sequence 693 * 694 * @param string $seq_name name of the sequence 695 * @param boolean $ondemand when true, the seqence is automatically 696 * created if it does not exist 697 * 698 * @return int the next id number in the sequence. 699 * A DB_Error object on failure. 700 * 701 * @see DB_common::nextID(), DB_common::getSequenceName(), 702 * DB_ibase::createSequence(), DB_ibase::dropSequence() 703 */ 704 function nextId($seq_name, $ondemand = true) 705 { 706 $sqn = strtoupper($this->getSequenceName($seq_name)); 707 $repeat = 0; 708 do { 709 $this->pushErrorHandling(PEAR_ERROR_RETURN); 710 $result =& $this->query("SELECT GEN_ID($sqn}, 1) " 711 . 'FROM RDB$GENERATORS ' 712 . "WHERE RDB\$GENERATOR_NAME='$sqn}'"); 713 $this->popErrorHandling(); 714 if ($ondemand && DB::isError($result)) { 715 $repeat = 1; 716 $result = $this->createSequence($seq_name); 717 if (DB::isError($result)) { 718 return $result; 719 } 720 } else { 721 $repeat = 0; 722 } 723 } while ($repeat); 724 if (DB::isError($result)) { 725 return $this->raiseError($result); 726 } 727 $arr = $result->fetchRow(DB_FETCHMODE_ORDERED); 728 $result->free(); 729 return $arr[0]; 730 } 731 732 // }}} 733 // {{{ createSequence() 734 735 /** 736 * Creates a new sequence 737 * 738 * @param string $seq_name name of the new sequence 739 * 740 * @return int DB_OK on success. A DB_Error object on failure. 741 * 742 * @see DB_common::createSequence(), DB_common::getSequenceName(), 743 * DB_ibase::nextID(), DB_ibase::dropSequence() 744 */ 745 function createSequence($seq_name) 746 { 747 $sqn = strtoupper($this->getSequenceName($seq_name)); 748 $this->pushErrorHandling(PEAR_ERROR_RETURN); 749 $result = $this->query("CREATE GENERATOR $sqn}"); 750 $this->popErrorHandling(); 751 752 return $result; 753 } 754 755 // }}} 756 // {{{ dropSequence() 757 758 /** 759 * Deletes a sequence 760 * 761 * @param string $seq_name name of the sequence to be deleted 762 * 763 * @return int DB_OK on success. A DB_Error object on failure. 764 * 765 * @see DB_common::dropSequence(), DB_common::getSequenceName(), 766 * DB_ibase::nextID(), DB_ibase::createSequence() 767 */ 768 function dropSequence($seq_name) 769 { 770 return $this->query('DELETE FROM RDB$GENERATORS ' 771 . "WHERE RDB\$GENERATOR_NAME='" 772 . strtoupper($this->getSequenceName($seq_name)) 773 . "'"); 774 } 775 776 // }}} 777 // {{{ _ibaseFieldFlags() 778 779 /** 780 * Get the column's flags 781 * 782 * Supports "primary_key", "unique_key", "not_null", "default", 783 * "computed" and "blob". 784 * 785 * @param string $field_name the name of the field 786 * @param string $table_name the name of the table 787 * 788 * @return string the flags 789 * 790 * @access private 791 */ 792 function _ibaseFieldFlags($field_name, $table_name) 793 { 794 $sql = 'SELECT R.RDB$CONSTRAINT_TYPE CTYPE' 795 .' FROM RDB$INDEX_SEGMENTS I' 796 .' JOIN RDB$RELATION_CONSTRAINTS R ON I.RDB$INDEX_NAME=R.RDB$INDEX_NAME' 797 .' WHERE I.RDB$FIELD_NAME=\'' . $field_name . '\'' 798 .' AND UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\''; 799 800 $result = @ibase_query($this->connection, $sql); 801 if (!$result) { 802 return $this->ibaseRaiseError(); 803 } 804 805 $flags = ''; 806 if ($obj = @ibase_fetch_object($result)) { 807 @ibase_free_result($result); 808 if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'PRIMARY KEY') { 809 $flags .= 'primary_key '; 810 } 811 if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'UNIQUE') { 812 $flags .= 'unique_key '; 813 } 814 } 815 816 $sql = 'SELECT R.RDB$NULL_FLAG AS NFLAG,' 817 .' R.RDB$DEFAULT_SOURCE AS DSOURCE,' 818 .' F.RDB$FIELD_TYPE AS FTYPE,' 819 .' F.RDB$COMPUTED_SOURCE AS CSOURCE' 820 .' FROM RDB$RELATION_FIELDS R ' 821 .' JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME' 822 .' WHERE UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\'' 823 .' AND R.RDB$FIELD_NAME=\'' . $field_name . '\''; 824 825 $result = @ibase_query($this->connection, $sql); 826 if (!$result) { 827 return $this->ibaseRaiseError(); 828 } 829 if ($obj = @ibase_fetch_object($result)) { 830 @ibase_free_result($result); 831 if (isset($obj->NFLAG)) { 832 $flags .= 'not_null '; 833 } 834 if (isset($obj->DSOURCE)) { 835 $flags .= 'default '; 836 } 837 if (isset($obj->CSOURCE)) { 838 $flags .= 'computed '; 839 } 840 if (isset($obj->FTYPE) && $obj->FTYPE == 261) { 841 $flags .= 'blob '; 842 } 843 } 844 845 return trim($flags); 846 } 847 848 // }}} 849 // {{{ ibaseRaiseError() 850 851 /** 852 * Produces a DB_Error object regarding the current problem 853 * 854 * @param int $errno if the error is being manually raised pass a 855 * DB_ERROR* constant here. If this isn't passed 856 * the error information gathered from the DBMS. 857 * 858 * @return object the DB_Error object 859 * 860 * @see DB_common::raiseError(), 861 * DB_ibase::errorNative(), DB_ibase::errorCode() 862 */ 863 function &ibaseRaiseError($errno = null) 864 { 865 if ($errno === null) { 866 $errno = $this->errorCode($this->errorNative()); 867 } 868 $tmp =& $this->raiseError($errno, null, null, null, @ibase_errmsg()); 869 return $tmp; 870 } 871 872 // }}} 873 // {{{ errorNative() 874 875 /** 876 * Gets the DBMS' native error code produced by the last query 877 * 878 * @return int the DBMS' error code. NULL if there is no error code. 879 * 880 * @since Method available since Release 1.7.0 881 */ 882 function errorNative() 883 { 884 if (function_exists('ibase_errcode')) { 885 return @ibase_errcode(); 886 } 887 if (preg_match('/^Dynamic SQL Error SQL error code = ([0-9-]+)/i', 888 @ibase_errmsg(), $m)) { 889 return (int)$m[1]; 890 } 891 return null; 892 } 893 894 // }}} 895 // {{{ errorCode() 896 897 /** 898 * Maps native error codes to DB's portable ones 899 * 900 * @param int $nativecode the error code returned by the DBMS 901 * 902 * @return int the portable DB error code. Return DB_ERROR if the 903 * current driver doesn't have a mapping for the 904 * $nativecode submitted. 905 * 906 * @since Method available since Release 1.7.0 907 */ 908 function errorCode($nativecode = null) 909 { 910 if (isset($this->errorcode_map[$nativecode])) { 911 return $this->errorcode_map[$nativecode]; 912 } 913 914 static $error_regexps; 915 if (!isset($error_regexps)) { 916 $error_regexps = array( 917 '/generator .* is not defined/' 918 => DB_ERROR_SYNTAX, // for compat. w ibase_errcode() 919 '/table.*(not exist|not found|unknown)/i' 920 => DB_ERROR_NOSUCHTABLE, 921 '/table .* already exists/i' 922 => DB_ERROR_ALREADY_EXISTS, 923 '/unsuccessful metadata update .* failed attempt to store duplicate value/i' 924 => DB_ERROR_ALREADY_EXISTS, 925 '/unsuccessful metadata update .* not found/i' 926 => DB_ERROR_NOT_FOUND, 927 '/validation error for column .* value "\*\*\* null/i' 928 => DB_ERROR_CONSTRAINT_NOT_NULL, 929 '/violation of [\w ]+ constraint/i' 930 => DB_ERROR_CONSTRAINT, 931 '/conversion error from string/i' 932 => DB_ERROR_INVALID_NUMBER, 933 '/no permission for/i' 934 => DB_ERROR_ACCESS_VIOLATION, 935 '/arithmetic exception, numeric overflow, or string truncation/i' 936 => DB_ERROR_INVALID, 937 '/feature is not supported/i' 938 => DB_ERROR_NOT_CAPABLE, 939 ); 940 } 941 942 $errormsg = @ibase_errmsg(); 943 foreach ($error_regexps as $regexp => $code) { 944 if (preg_match($regexp, $errormsg)) { 945 return $code; 946 } 947 } 948 return DB_ERROR; 949 } 950 951 // }}} 952 // {{{ tableInfo() 953 954 /** 955 * Returns information about a table or a result set 956 * 957 * NOTE: only supports 'table' and 'flags' if <var>$result</var> 958 * is a table name. 959 * 960 * @param object|string $result DB_result object from a query or a 961 * string containing the name of a table. 962 * While this also accepts a query result 963 * resource identifier, this behavior is 964 * deprecated. 965 * @param int $mode a valid tableInfo mode 966 * 967 * @return array an associative array with the information requested. 968 * A DB_Error object on failure. 969 * 970 * @see DB_common::tableInfo() 971 */ 972 function tableInfo($result, $mode = null) 973 { 974 if (is_string($result)) { 975 /* 976 * Probably received a table name. 977 * Create a result resource identifier. 978 */ 979 $id = @ibase_query($this->connection, 980 "SELECT * FROM $result WHERE 1=0"); 981 $got_string = true; 982 } elseif (isset($result->result)) { 983 /* 984 * Probably received a result object. 985 * Extract the result resource identifier. 986 */ 987 $id = $result->result; 988 $got_string = false; 989 } else { 990 /* 991 * Probably received a result resource identifier. 992 * Copy it. 993 * Deprecated. Here for compatibility only. 994 */ 995 $id = $result; 996 $got_string = false; 997 } 998 999 if (!is_resource($id)) { 1000 return $this->ibaseRaiseError(DB_ERROR_NEED_MORE_DATA); 1001 } 1002 1003 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 1004 $case_func = 'strtolower'; 1005 } else { 1006 $case_func = 'strval'; 1007 } 1008 1009 $count = @ibase_num_fields($id); 1010 $res = array(); 1011 1012 if ($mode) { 1013 $res['num_fields'] = $count; 1014 } 1015 1016 for ($i = 0; $i < $count; $i++) { 1017 $info = @ibase_field_info($id, $i); 1018 $res[$i] = array( 1019 'table' => $got_string ? $case_func($result) : '', 1020 'name' => $case_func($info['name']), 1021 'type' => $info['type'], 1022 'len' => $info['length'], 1023 'flags' => ($got_string) 1024 ? $this->_ibaseFieldFlags($info['name'], $result) 1025 : '', 1026 ); 1027 if ($mode & DB_TABLEINFO_ORDER) { 1028 $res['order'][$res[$i]['name']] = $i; 1029 } 1030 if ($mode & DB_TABLEINFO_ORDERTABLE) { 1031 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 1032 } 1033 } 1034 1035 // free the result only if we were called on a table 1036 if ($got_string) { 1037 @ibase_free_result($id); 1038 } 1039 return $res; 1040 } 1041 1042 // }}} 1043 // {{{ getSpecialQuery() 1044 1045 /** 1046 * Obtains the query string needed for listing a given type of objects 1047 * 1048 * @param string $type the kind of objects you want to retrieve 1049 * 1050 * @return string the SQL query string or null if the driver doesn't 1051 * support the object type requested 1052 * 1053 * @access protected 1054 * @see DB_common::getListOf() 1055 */ 1056 function getSpecialQuery($type) 1057 { 1058 switch ($type) { 1059 case 'tables': 1060 return 'SELECT DISTINCT R.RDB$RELATION_NAME FROM ' 1061 . 'RDB$RELATION_FIELDS R WHERE R.RDB$SYSTEM_FLAG=0'; 1062 case 'views': 1063 return 'SELECT DISTINCT RDB$VIEW_NAME from RDB$VIEW_RELATIONS'; 1064 case 'users': 1065 return 'SELECT DISTINCT RDB$USER FROM RDB$USER_PRIVILEGES'; 1066 default: 1067 return null; 1068 } 1069 } 1070 1071 // }}} 1072 1073 } 1074 1075 /* 1076 * Local variables: 1077 * tab-width: 4 1078 * c-basic-offset: 4 1079 * End: 1080 */ 1081 1082 ?>
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 |