[ 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 sybase extension 7 * for interacting with Sybase databases 8 * 9 * PHP versions 4 and 5 10 * 11 * LICENSE: This source file is subject to version 3.0 of the PHP license 12 * that is available through the world-wide-web at the following URI: 13 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 14 * the PHP License and are unable to obtain it through the web, please 15 * send a note to license@php.net so we can mail you a copy immediately. 16 * 17 * @category Database 18 * @package DB 19 * @author Sterling Hughes <sterling@php.net> 20 * @author Antônio Carlos Venâncio Júnior <floripa@php.net> 21 * @author Daniel Convissor <danielc@php.net> 22 * @copyright 1997-2005 The PHP Group 23 * @license http://www.php.net/license/3_0.txt PHP License 3.0 24 * @version CVS: $Id: sybase.php,v 1.85 2007/02/06 07:35:07 aharvey Exp $ 25 * @link http://pear.php.net/package/DB 26 */ 27 28 /** 29 * Obtain the DB_common class so it can be extended from 30 */ 31 require_once 'DB/common.php'; 32 33 /** 34 * The methods PEAR DB uses to interact with PHP's sybase extension 35 * for interacting with Sybase databases 36 * 37 * These methods overload the ones declared in DB_common. 38 * 39 * WARNING: This driver may fail with multiple connections under the 40 * same user/pass/host and different databases. 41 * 42 * @category Database 43 * @package DB 44 * @author Sterling Hughes <sterling@php.net> 45 * @author Antônio Carlos Venâncio Júnior <floripa@php.net> 46 * @author Daniel Convissor <danielc@php.net> 47 * @copyright 1997-2005 The PHP Group 48 * @license http://www.php.net/license/3_0.txt PHP License 3.0 49 * @version Release: 1.7.9 50 * @link http://pear.php.net/package/DB 51 */ 52 class DB_sybase extends DB_common 53 { 54 // {{{ properties 55 56 /** 57 * The DB driver type (mysql, oci8, odbc, etc.) 58 * @var string 59 */ 60 var $phptype = 'sybase'; 61 62 /** 63 * The database syntax variant to be used (db2, access, etc.), if any 64 * @var string 65 */ 66 var $dbsyntax = 'sybase'; 67 68 /** 69 * The capabilities of this DB implementation 70 * 71 * The 'new_link' element contains the PHP version that first provided 72 * new_link support for this DBMS. Contains false if it's unsupported. 73 * 74 * Meaning of the 'limit' element: 75 * + 'emulate' = emulate with fetch row by number 76 * + 'alter' = alter the query 77 * + false = skip rows 78 * 79 * @var array 80 */ 81 var $features = array( 82 'limit' => 'emulate', 83 'new_link' => false, 84 'numrows' => true, 85 'pconnect' => true, 86 'prepare' => false, 87 'ssl' => false, 88 'transactions' => true, 89 ); 90 91 /** 92 * A mapping of native error codes to DB error codes 93 * @var array 94 */ 95 var $errorcode_map = array( 96 ); 97 98 /** 99 * The raw database connection created by PHP 100 * @var resource 101 */ 102 var $connection; 103 104 /** 105 * The DSN information for connecting to a database 106 * @var array 107 */ 108 var $dsn = array(); 109 110 111 /** 112 * Should data manipulation queries be committed automatically? 113 * @var bool 114 * @access private 115 */ 116 var $autocommit = true; 117 118 /** 119 * The quantity of transactions begun 120 * 121 * {@internal While this is private, it can't actually be designated 122 * private in PHP 5 because it is directly accessed in the test suite.}} 123 * 124 * @var integer 125 * @access private 126 */ 127 var $transaction_opcount = 0; 128 129 /** 130 * The database specified in the DSN 131 * 132 * It's a fix to allow calls to different databases in the same script. 133 * 134 * @var string 135 * @access private 136 */ 137 var $_db = ''; 138 139 140 // }}} 141 // {{{ constructor 142 143 /** 144 * This constructor calls <kbd>$this->DB_common()</kbd> 145 * 146 * @return void 147 */ 148 function DB_sybase() 149 { 150 $this->DB_common(); 151 } 152 153 // }}} 154 // {{{ connect() 155 156 /** 157 * Connect to the database server, log in and open the database 158 * 159 * Don't call this method directly. Use DB::connect() instead. 160 * 161 * PEAR DB's sybase driver supports the following extra DSN options: 162 * + appname The application name to use on this connection. 163 * Available since PEAR DB 1.7.0. 164 * + charset The character set to use on this connection. 165 * Available since PEAR DB 1.7.0. 166 * 167 * @param array $dsn the data source name 168 * @param bool $persistent should the connection be persistent? 169 * 170 * @return int DB_OK on success. A DB_Error object on failure. 171 */ 172 function connect($dsn, $persistent = false) 173 { 174 if (!PEAR::loadExtension('sybase') && 175 !PEAR::loadExtension('sybase_ct')) 176 { 177 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 178 } 179 180 $this->dsn = $dsn; 181 if ($dsn['dbsyntax']) { 182 $this->dbsyntax = $dsn['dbsyntax']; 183 } 184 185 $dsn['hostspec'] = $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost'; 186 $dsn['password'] = !empty($dsn['password']) ? $dsn['password'] : false; 187 $dsn['charset'] = isset($dsn['charset']) ? $dsn['charset'] : false; 188 $dsn['appname'] = isset($dsn['appname']) ? $dsn['appname'] : false; 189 190 $connect_function = $persistent ? 'sybase_pconnect' : 'sybase_connect'; 191 192 if ($dsn['username']) { 193 $this->connection = @$connect_function($dsn['hostspec'], 194 $dsn['username'], 195 $dsn['password'], 196 $dsn['charset'], 197 $dsn['appname']); 198 } else { 199 return $this->raiseError(DB_ERROR_CONNECT_FAILED, 200 null, null, null, 201 'The DSN did not contain a username.'); 202 } 203 204 if (!$this->connection) { 205 return $this->raiseError(DB_ERROR_CONNECT_FAILED, 206 null, null, null, 207 @sybase_get_last_message()); 208 } 209 210 if ($dsn['database']) { 211 if (!@sybase_select_db($dsn['database'], $this->connection)) { 212 return $this->raiseError(DB_ERROR_NODBSELECTED, 213 null, null, null, 214 @sybase_get_last_message()); 215 } 216 $this->_db = $dsn['database']; 217 } 218 219 return DB_OK; 220 } 221 222 // }}} 223 // {{{ disconnect() 224 225 /** 226 * Disconnects from the database server 227 * 228 * @return bool TRUE on success, FALSE on failure 229 */ 230 function disconnect() 231 { 232 $ret = @sybase_close($this->connection); 233 $this->connection = null; 234 return $ret; 235 } 236 237 // }}} 238 // {{{ simpleQuery() 239 240 /** 241 * Sends a query to the database server 242 * 243 * @param string the SQL query string 244 * 245 * @return mixed + a PHP result resrouce for successful SELECT queries 246 * + the DB_OK constant for other successful queries 247 * + a DB_Error object on failure 248 */ 249 function simpleQuery($query) 250 { 251 $ismanip = $this->_checkManip($query); 252 $this->last_query = $query; 253 if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { 254 return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); 255 } 256 $query = $this->modifyQuery($query); 257 if (!$this->autocommit && $ismanip) { 258 if ($this->transaction_opcount == 0) { 259 $result = @sybase_query('BEGIN TRANSACTION', $this->connection); 260 if (!$result) { 261 return $this->sybaseRaiseError(); 262 } 263 } 264 $this->transaction_opcount++; 265 } 266 $result = @sybase_query($query, $this->connection); 267 if (!$result) { 268 return $this->sybaseRaiseError(); 269 } 270 if (is_resource($result)) { 271 return $result; 272 } 273 // Determine which queries that should return data, and which 274 // should return an error code only. 275 return $ismanip ? DB_OK : $result; 276 } 277 278 // }}} 279 // {{{ nextResult() 280 281 /** 282 * Move the internal sybase result pointer to the next available result 283 * 284 * @param a valid sybase result resource 285 * 286 * @access public 287 * 288 * @return true if a result is available otherwise return false 289 */ 290 function nextResult($result) 291 { 292 return false; 293 } 294 295 // }}} 296 // {{{ fetchInto() 297 298 /** 299 * Places a row from the result set into the given array 300 * 301 * Formating of the array and the data therein are configurable. 302 * See DB_result::fetchInto() for more information. 303 * 304 * This method is not meant to be called directly. Use 305 * DB_result::fetchInto() instead. It can't be declared "protected" 306 * because DB_result is a separate object. 307 * 308 * @param resource $result the query result resource 309 * @param array $arr the referenced array to put the data in 310 * @param int $fetchmode how the resulting array should be indexed 311 * @param int $rownum the row number to fetch (0 = first row) 312 * 313 * @return mixed DB_OK on success, NULL when the end of a result set is 314 * reached or on failure 315 * 316 * @see DB_result::fetchInto() 317 */ 318 function fetchInto($result, &$arr, $fetchmode, $rownum = null) 319 { 320 if ($rownum !== null) { 321 if (!@sybase_data_seek($result, $rownum)) { 322 return null; 323 } 324 } 325 if ($fetchmode & DB_FETCHMODE_ASSOC) { 326 if (function_exists('sybase_fetch_assoc')) { 327 $arr = @sybase_fetch_assoc($result); 328 } else { 329 if ($arr = @sybase_fetch_array($result)) { 330 foreach ($arr as $key => $value) { 331 if (is_int($key)) { 332 unset($arr[$key]); 333 } 334 } 335 } 336 } 337 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { 338 $arr = array_change_key_case($arr, CASE_LOWER); 339 } 340 } else { 341 $arr = @sybase_fetch_row($result); 342 } 343 if (!$arr) { 344 return null; 345 } 346 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 347 $this->_rtrimArrayValues($arr); 348 } 349 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 350 $this->_convertNullArrayValuesToEmpty($arr); 351 } 352 return DB_OK; 353 } 354 355 // }}} 356 // {{{ freeResult() 357 358 /** 359 * Deletes the result set and frees the memory occupied by the result set 360 * 361 * This method is not meant to be called directly. Use 362 * DB_result::free() instead. It can't be declared "protected" 363 * because DB_result is a separate object. 364 * 365 * @param resource $result PHP's query result resource 366 * 367 * @return bool TRUE on success, FALSE if $result is invalid 368 * 369 * @see DB_result::free() 370 */ 371 function freeResult($result) 372 { 373 return is_resource($result) ? sybase_free_result($result) : false; 374 } 375 376 // }}} 377 // {{{ numCols() 378 379 /** 380 * Gets the number of columns in a result set 381 * 382 * This method is not meant to be called directly. Use 383 * DB_result::numCols() instead. It can't be declared "protected" 384 * because DB_result is a separate object. 385 * 386 * @param resource $result PHP's query result resource 387 * 388 * @return int the number of columns. A DB_Error object on failure. 389 * 390 * @see DB_result::numCols() 391 */ 392 function numCols($result) 393 { 394 $cols = @sybase_num_fields($result); 395 if (!$cols) { 396 return $this->sybaseRaiseError(); 397 } 398 return $cols; 399 } 400 401 // }}} 402 // {{{ numRows() 403 404 /** 405 * Gets the number of rows in a result set 406 * 407 * This method is not meant to be called directly. Use 408 * DB_result::numRows() instead. It can't be declared "protected" 409 * because DB_result is a separate object. 410 * 411 * @param resource $result PHP's query result resource 412 * 413 * @return int the number of rows. A DB_Error object on failure. 414 * 415 * @see DB_result::numRows() 416 */ 417 function numRows($result) 418 { 419 $rows = @sybase_num_rows($result); 420 if ($rows === false) { 421 return $this->sybaseRaiseError(); 422 } 423 return $rows; 424 } 425 426 // }}} 427 // {{{ affectedRows() 428 429 /** 430 * Determines the number of rows affected by a data maniuplation query 431 * 432 * 0 is returned for queries that don't manipulate data. 433 * 434 * @return int the number of rows. A DB_Error object on failure. 435 */ 436 function affectedRows() 437 { 438 if ($this->_last_query_manip) { 439 $result = @sybase_affected_rows($this->connection); 440 } else { 441 $result = 0; 442 } 443 return $result; 444 } 445 446 // }}} 447 // {{{ nextId() 448 449 /** 450 * Returns the next free id in a sequence 451 * 452 * @param string $seq_name name of the sequence 453 * @param boolean $ondemand when true, the seqence is automatically 454 * created if it does not exist 455 * 456 * @return int the next id number in the sequence. 457 * A DB_Error object on failure. 458 * 459 * @see DB_common::nextID(), DB_common::getSequenceName(), 460 * DB_sybase::createSequence(), DB_sybase::dropSequence() 461 */ 462 function nextId($seq_name, $ondemand = true) 463 { 464 $seqname = $this->getSequenceName($seq_name); 465 if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { 466 return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); 467 } 468 $repeat = 0; 469 do { 470 $this->pushErrorHandling(PEAR_ERROR_RETURN); 471 $result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)"); 472 $this->popErrorHandling(); 473 if ($ondemand && DB::isError($result) && 474 ($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE)) 475 { 476 $repeat = 1; 477 $result = $this->createSequence($seq_name); 478 if (DB::isError($result)) { 479 return $this->raiseError($result); 480 } 481 } elseif (!DB::isError($result)) { 482 $result =& $this->query("SELECT @@IDENTITY FROM $seqname"); 483 $repeat = 0; 484 } else { 485 $repeat = false; 486 } 487 } while ($repeat); 488 if (DB::isError($result)) { 489 return $this->raiseError($result); 490 } 491 $result = $result->fetchRow(DB_FETCHMODE_ORDERED); 492 return $result[0]; 493 } 494 495 /** 496 * Creates a new sequence 497 * 498 * @param string $seq_name name of the new sequence 499 * 500 * @return int DB_OK on success. A DB_Error object on failure. 501 * 502 * @see DB_common::createSequence(), DB_common::getSequenceName(), 503 * DB_sybase::nextID(), DB_sybase::dropSequence() 504 */ 505 function createSequence($seq_name) 506 { 507 return $this->query('CREATE TABLE ' 508 . $this->getSequenceName($seq_name) 509 . ' (id numeric(10, 0) IDENTITY NOT NULL,' 510 . ' vapor int NULL)'); 511 } 512 513 // }}} 514 // {{{ dropSequence() 515 516 /** 517 * Deletes a sequence 518 * 519 * @param string $seq_name name of the sequence to be deleted 520 * 521 * @return int DB_OK on success. A DB_Error object on failure. 522 * 523 * @see DB_common::dropSequence(), DB_common::getSequenceName(), 524 * DB_sybase::nextID(), DB_sybase::createSequence() 525 */ 526 function dropSequence($seq_name) 527 { 528 return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); 529 } 530 531 // }}} 532 // {{{ quoteFloat() 533 534 /** 535 * Formats a float value for use within a query in a locale-independent 536 * manner. 537 * 538 * @param float the float value to be quoted. 539 * @return string the quoted string. 540 * @see DB_common::quoteSmart() 541 * @since Method available since release 1.7.8. 542 */ 543 function quoteFloat($float) { 544 return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); 545 } 546 547 // }}} 548 // {{{ autoCommit() 549 550 /** 551 * Enables or disables automatic commits 552 * 553 * @param bool $onoff true turns it on, false turns it off 554 * 555 * @return int DB_OK on success. A DB_Error object if the driver 556 * doesn't support auto-committing transactions. 557 */ 558 function autoCommit($onoff = false) 559 { 560 // XXX if $this->transaction_opcount > 0, we should probably 561 // issue a warning here. 562 $this->autocommit = $onoff ? true : false; 563 return DB_OK; 564 } 565 566 // }}} 567 // {{{ commit() 568 569 /** 570 * Commits the current transaction 571 * 572 * @return int DB_OK on success. A DB_Error object on failure. 573 */ 574 function commit() 575 { 576 if ($this->transaction_opcount > 0) { 577 if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { 578 return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); 579 } 580 $result = @sybase_query('COMMIT', $this->connection); 581 $this->transaction_opcount = 0; 582 if (!$result) { 583 return $this->sybaseRaiseError(); 584 } 585 } 586 return DB_OK; 587 } 588 589 // }}} 590 // {{{ rollback() 591 592 /** 593 * Reverts the current transaction 594 * 595 * @return int DB_OK on success. A DB_Error object on failure. 596 */ 597 function rollback() 598 { 599 if ($this->transaction_opcount > 0) { 600 if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { 601 return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); 602 } 603 $result = @sybase_query('ROLLBACK', $this->connection); 604 $this->transaction_opcount = 0; 605 if (!$result) { 606 return $this->sybaseRaiseError(); 607 } 608 } 609 return DB_OK; 610 } 611 612 // }}} 613 // {{{ sybaseRaiseError() 614 615 /** 616 * Produces a DB_Error object regarding the current problem 617 * 618 * @param int $errno if the error is being manually raised pass a 619 * DB_ERROR* constant here. If this isn't passed 620 * the error information gathered from the DBMS. 621 * 622 * @return object the DB_Error object 623 * 624 * @see DB_common::raiseError(), 625 * DB_sybase::errorNative(), DB_sybase::errorCode() 626 */ 627 function sybaseRaiseError($errno = null) 628 { 629 $native = $this->errorNative(); 630 if ($errno === null) { 631 $errno = $this->errorCode($native); 632 } 633 return $this->raiseError($errno, null, null, null, $native); 634 } 635 636 // }}} 637 // {{{ errorNative() 638 639 /** 640 * Gets the DBMS' native error message produced by the last query 641 * 642 * @return string the DBMS' error message 643 */ 644 function errorNative() 645 { 646 return @sybase_get_last_message(); 647 } 648 649 // }}} 650 // {{{ errorCode() 651 652 /** 653 * Determines PEAR::DB error code from the database's text error message. 654 * 655 * @param string $errormsg error message returned from the database 656 * @return integer an error number from a DB error constant 657 */ 658 function errorCode($errormsg) 659 { 660 static $error_regexps; 661 662 // PHP 5.2+ prepends the function name to $php_errormsg, so we need 663 // this hack to work around it, per bug #9599. 664 $errormsg = preg_replace('/^sybase[a-z_]+\(\): /', '', $errormsg); 665 666 if (!isset($error_regexps)) { 667 $error_regexps = array( 668 '/Incorrect syntax near/' 669 => DB_ERROR_SYNTAX, 670 '/^Unclosed quote before the character string [\"\'].*[\"\']\./' 671 => DB_ERROR_SYNTAX, 672 '/Implicit conversion (from datatype|of NUMERIC value)/i' 673 => DB_ERROR_INVALID_NUMBER, 674 '/Cannot drop the table [\"\'].+[\"\'], because it doesn\'t exist in the system catalogs\./' 675 => DB_ERROR_NOSUCHTABLE, 676 '/Only the owner of object [\"\'].+[\"\'] or a user with System Administrator \(SA\) role can run this command\./' 677 => DB_ERROR_ACCESS_VIOLATION, 678 '/^.+ permission denied on object .+, database .+, owner .+/' 679 => DB_ERROR_ACCESS_VIOLATION, 680 '/^.* permission denied, database .+, owner .+/' 681 => DB_ERROR_ACCESS_VIOLATION, 682 '/[^.*] not found\./' 683 => DB_ERROR_NOSUCHTABLE, 684 '/There is already an object named/' 685 => DB_ERROR_ALREADY_EXISTS, 686 '/Invalid column name/' 687 => DB_ERROR_NOSUCHFIELD, 688 '/does not allow null values/' 689 => DB_ERROR_CONSTRAINT_NOT_NULL, 690 '/Command has been aborted/' 691 => DB_ERROR_CONSTRAINT, 692 '/^Cannot drop the index .* because it doesn\'t exist/i' 693 => DB_ERROR_NOT_FOUND, 694 '/^There is already an index/i' 695 => DB_ERROR_ALREADY_EXISTS, 696 '/^There are fewer columns in the INSERT statement than values specified/i' 697 => DB_ERROR_VALUE_COUNT_ON_ROW, 698 '/Divide by zero/i' 699 => DB_ERROR_DIVZERO, 700 ); 701 } 702 703 foreach ($error_regexps as $regexp => $code) { 704 if (preg_match($regexp, $errormsg)) { 705 return $code; 706 } 707 } 708 return DB_ERROR; 709 } 710 711 // }}} 712 // {{{ tableInfo() 713 714 /** 715 * Returns information about a table or a result set 716 * 717 * NOTE: only supports 'table' and 'flags' if <var>$result</var> 718 * is a table name. 719 * 720 * @param object|string $result DB_result object from a query or a 721 * string containing the name of a table. 722 * While this also accepts a query result 723 * resource identifier, this behavior is 724 * deprecated. 725 * @param int $mode a valid tableInfo mode 726 * 727 * @return array an associative array with the information requested. 728 * A DB_Error object on failure. 729 * 730 * @see DB_common::tableInfo() 731 * @since Method available since Release 1.6.0 732 */ 733 function tableInfo($result, $mode = null) 734 { 735 if (is_string($result)) { 736 /* 737 * Probably received a table name. 738 * Create a result resource identifier. 739 */ 740 if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { 741 return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); 742 } 743 $id = @sybase_query("SELECT * FROM $result WHERE 1=0", 744 $this->connection); 745 $got_string = true; 746 } elseif (isset($result->result)) { 747 /* 748 * Probably received a result object. 749 * Extract the result resource identifier. 750 */ 751 $id = $result->result; 752 $got_string = false; 753 } else { 754 /* 755 * Probably received a result resource identifier. 756 * Copy it. 757 * Deprecated. Here for compatibility only. 758 */ 759 $id = $result; 760 $got_string = false; 761 } 762 763 if (!is_resource($id)) { 764 return $this->sybaseRaiseError(DB_ERROR_NEED_MORE_DATA); 765 } 766 767 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 768 $case_func = 'strtolower'; 769 } else { 770 $case_func = 'strval'; 771 } 772 773 $count = @sybase_num_fields($id); 774 $res = array(); 775 776 if ($mode) { 777 $res['num_fields'] = $count; 778 } 779 780 for ($i = 0; $i < $count; $i++) { 781 $f = @sybase_fetch_field($id, $i); 782 // column_source is often blank 783 $res[$i] = array( 784 'table' => $got_string 785 ? $case_func($result) 786 : $case_func($f->column_source), 787 'name' => $case_func($f->name), 788 'type' => $f->type, 789 'len' => $f->max_length, 790 'flags' => '', 791 ); 792 if ($res[$i]['table']) { 793 $res[$i]['flags'] = $this->_sybase_field_flags( 794 $res[$i]['table'], $res[$i]['name']); 795 } 796 if ($mode & DB_TABLEINFO_ORDER) { 797 $res['order'][$res[$i]['name']] = $i; 798 } 799 if ($mode & DB_TABLEINFO_ORDERTABLE) { 800 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 801 } 802 } 803 804 // free the result only if we were called on a table 805 if ($got_string) { 806 @sybase_free_result($id); 807 } 808 return $res; 809 } 810 811 // }}} 812 // {{{ _sybase_field_flags() 813 814 /** 815 * Get the flags for a field 816 * 817 * Currently supports: 818 * + <samp>unique_key</samp> (unique index, unique check or primary_key) 819 * + <samp>multiple_key</samp> (multi-key index) 820 * 821 * @param string $table the table name 822 * @param string $column the field name 823 * 824 * @return string space delimited string of flags. Empty string if none. 825 * 826 * @access private 827 */ 828 function _sybase_field_flags($table, $column) 829 { 830 static $tableName = null; 831 static $flags = array(); 832 833 if ($table != $tableName) { 834 $flags = array(); 835 $tableName = $table; 836 837 /* We're running sp_helpindex directly because it doesn't exist in 838 * older versions of ASE -- unfortunately, we can't just use 839 * DB::isError() because the user may be using callback error 840 * handling. */ 841 $res = @sybase_query("sp_helpindex $table", $this->connection); 842 843 if ($res === false || $res === true) { 844 // Fake a valid response for BC reasons. 845 return ''; 846 } 847 848 while (($val = sybase_fetch_assoc($res)) !== false) { 849 if (!isset($val['index_keys'])) { 850 /* No useful information returned. Break and be done with 851 * it, which preserves the pre-1.7.9 behaviour. */ 852 break; 853 } 854 855 $keys = explode(', ', trim($val['index_keys'])); 856 857 if (sizeof($keys) > 1) { 858 foreach ($keys as $key) { 859 $this->_add_flag($flags[$key], 'multiple_key'); 860 } 861 } 862 863 if (strpos($val['index_description'], 'unique')) { 864 foreach ($keys as $key) { 865 $this->_add_flag($flags[$key], 'unique_key'); 866 } 867 } 868 } 869 870 sybase_free_result($res); 871 872 } 873 874 if (array_key_exists($column, $flags)) { 875 return(implode(' ', $flags[$column])); 876 } 877 878 return ''; 879 } 880 881 // }}} 882 // {{{ _add_flag() 883 884 /** 885 * Adds a string to the flags array if the flag is not yet in there 886 * - if there is no flag present the array is created 887 * 888 * @param array $array reference of flags array to add a value to 889 * @param mixed $value value to add to the flag array 890 * 891 * @return void 892 * 893 * @access private 894 */ 895 function _add_flag(&$array, $value) 896 { 897 if (!is_array($array)) { 898 $array = array($value); 899 } elseif (!in_array($value, $array)) { 900 array_push($array, $value); 901 } 902 } 903 904 // }}} 905 // {{{ getSpecialQuery() 906 907 /** 908 * Obtains the query string needed for listing a given type of objects 909 * 910 * @param string $type the kind of objects you want to retrieve 911 * 912 * @return string the SQL query string or null if the driver doesn't 913 * support the object type requested 914 * 915 * @access protected 916 * @see DB_common::getListOf() 917 */ 918 function getSpecialQuery($type) 919 { 920 switch ($type) { 921 case 'tables': 922 return "SELECT name FROM sysobjects WHERE type = 'U'" 923 . ' ORDER BY name'; 924 case 'views': 925 return "SELECT name FROM sysobjects WHERE type = 'V'"; 926 default: 927 return null; 928 } 929 } 930 931 // }}} 932 933 } 934 935 /* 936 * Local variables: 937 * tab-width: 4 938 * c-basic-offset: 4 939 * End: 940 */ 941 942 ?>
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 |