[ 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 msql extension 7 * for interacting with Mini SQL databases 8 * 9 * PHP's mSQL extension did weird things with NULL values prior to PHP 10 * 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds 11 * those versions. 12 * 13 * PHP versions 4 and 5 14 * 15 * LICENSE: This source file is subject to version 3.0 of the PHP license 16 * that is available through the world-wide-web at the following URI: 17 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 18 * the PHP License and are unable to obtain it through the web, please 19 * send a note to license@php.net so we can mail you a copy immediately. 20 * 21 * @category Database 22 * @package DB 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: msql.php,v 1.62 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 msql extension 37 * for interacting with Mini SQL databases 38 * 39 * These methods overload the ones declared in DB_common. 40 * 41 * PHP's mSQL extension did weird things with NULL values prior to PHP 42 * 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds 43 * those versions. 44 * 45 * @category Database 46 * @package DB 47 * @author Daniel Convissor <danielc@php.net> 48 * @copyright 1997-2005 The PHP Group 49 * @license http://www.php.net/license/3_0.txt PHP License 3.0 50 * @version Release: 1.7.9 51 * @link http://pear.php.net/package/DB 52 * @since Class not functional until Release 1.7.0 53 */ 54 class DB_msql extends DB_common 55 { 56 // {{{ properties 57 58 /** 59 * The DB driver type (mysql, oci8, odbc, etc.) 60 * @var string 61 */ 62 var $phptype = 'msql'; 63 64 /** 65 * The database syntax variant to be used (db2, access, etc.), if any 66 * @var string 67 */ 68 var $dbsyntax = 'msql'; 69 70 /** 71 * The capabilities of this DB implementation 72 * 73 * The 'new_link' element contains the PHP version that first provided 74 * new_link support for this DBMS. Contains false if it's unsupported. 75 * 76 * Meaning of the 'limit' element: 77 * + 'emulate' = emulate with fetch row by number 78 * + 'alter' = alter the query 79 * + false = skip rows 80 * 81 * @var array 82 */ 83 var $features = array( 84 'limit' => 'emulate', 85 'new_link' => false, 86 'numrows' => true, 87 'pconnect' => true, 88 'prepare' => false, 89 'ssl' => false, 90 'transactions' => false, 91 ); 92 93 /** 94 * A mapping of native error codes to DB error codes 95 * @var array 96 */ 97 var $errorcode_map = array( 98 ); 99 100 /** 101 * The raw database connection created by PHP 102 * @var resource 103 */ 104 var $connection; 105 106 /** 107 * The DSN information for connecting to a database 108 * @var array 109 */ 110 var $dsn = array(); 111 112 113 /** 114 * The query result resource created by PHP 115 * 116 * Used to make affectedRows() work. Only contains the result for 117 * data manipulation queries. Contains false for other queries. 118 * 119 * @var resource 120 * @access private 121 */ 122 var $_result; 123 124 125 // }}} 126 // {{{ constructor 127 128 /** 129 * This constructor calls <kbd>$this->DB_common()</kbd> 130 * 131 * @return void 132 */ 133 function DB_msql() 134 { 135 $this->DB_common(); 136 } 137 138 // }}} 139 // {{{ connect() 140 141 /** 142 * Connect to the database server, log in and open the database 143 * 144 * Don't call this method directly. Use DB::connect() instead. 145 * 146 * Example of how to connect: 147 * <code> 148 * require_once 'DB.php'; 149 * 150 * // $dsn = 'msql://hostname/dbname'; // use a TCP connection 151 * $dsn = 'msql:///dbname'; // use a socket 152 * $options = array( 153 * 'portability' => DB_PORTABILITY_ALL, 154 * ); 155 * 156 * $db =& DB::connect($dsn, $options); 157 * if (PEAR::isError($db)) { 158 * die($db->getMessage()); 159 * } 160 * </code> 161 * 162 * @param array $dsn the data source name 163 * @param bool $persistent should the connection be persistent? 164 * 165 * @return int DB_OK on success. A DB_Error object on failure. 166 */ 167 function connect($dsn, $persistent = false) 168 { 169 if (!PEAR::loadExtension('msql')) { 170 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 171 } 172 173 $this->dsn = $dsn; 174 if ($dsn['dbsyntax']) { 175 $this->dbsyntax = $dsn['dbsyntax']; 176 } 177 178 $params = array(); 179 if ($dsn['hostspec']) { 180 $params[] = $dsn['port'] 181 ? $dsn['hostspec'] . ',' . $dsn['port'] 182 : $dsn['hostspec']; 183 } 184 185 $connect_function = $persistent ? 'msql_pconnect' : 'msql_connect'; 186 187 $ini = ini_get('track_errors'); 188 $php_errormsg = ''; 189 if ($ini) { 190 $this->connection = @call_user_func_array($connect_function, 191 $params); 192 } else { 193 @ini_set('track_errors', 1); 194 $this->connection = @call_user_func_array($connect_function, 195 $params); 196 @ini_set('track_errors', $ini); 197 } 198 199 if (!$this->connection) { 200 if (($err = @msql_error()) != '') { 201 return $this->raiseError(DB_ERROR_CONNECT_FAILED, 202 null, null, null, 203 $err); 204 } else { 205 return $this->raiseError(DB_ERROR_CONNECT_FAILED, 206 null, null, null, 207 $php_errormsg); 208 } 209 } 210 211 if (!@msql_select_db($dsn['database'], $this->connection)) { 212 return $this->msqlRaiseError(); 213 } 214 return DB_OK; 215 } 216 217 // }}} 218 // {{{ disconnect() 219 220 /** 221 * Disconnects from the database server 222 * 223 * @return bool TRUE on success, FALSE on failure 224 */ 225 function disconnect() 226 { 227 $ret = @msql_close($this->connection); 228 $this->connection = null; 229 return $ret; 230 } 231 232 // }}} 233 // {{{ simpleQuery() 234 235 /** 236 * Sends a query to the database server 237 * 238 * @param string the SQL query string 239 * 240 * @return mixed + a PHP result resrouce for successful SELECT queries 241 * + the DB_OK constant for other successful queries 242 * + a DB_Error object on failure 243 */ 244 function simpleQuery($query) 245 { 246 $this->last_query = $query; 247 $query = $this->modifyQuery($query); 248 $result = @msql_query($query, $this->connection); 249 if (!$result) { 250 return $this->msqlRaiseError(); 251 } 252 // Determine which queries that should return data, and which 253 // should return an error code only. 254 if ($this->_checkManip($query)) { 255 $this->_result = $result; 256 return DB_OK; 257 } else { 258 $this->_result = false; 259 return $result; 260 } 261 } 262 263 264 // }}} 265 // {{{ nextResult() 266 267 /** 268 * Move the internal msql result pointer to the next available result 269 * 270 * @param a valid fbsql result resource 271 * 272 * @access public 273 * 274 * @return true if a result is available otherwise return false 275 */ 276 function nextResult($result) 277 { 278 return false; 279 } 280 281 // }}} 282 // {{{ fetchInto() 283 284 /** 285 * Places a row from the result set into the given array 286 * 287 * Formating of the array and the data therein are configurable. 288 * See DB_result::fetchInto() for more information. 289 * 290 * This method is not meant to be called directly. Use 291 * DB_result::fetchInto() instead. It can't be declared "protected" 292 * because DB_result is a separate object. 293 * 294 * PHP's mSQL extension did weird things with NULL values prior to PHP 295 * 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds 296 * those versions. 297 * 298 * @param resource $result the query result resource 299 * @param array $arr the referenced array to put the data in 300 * @param int $fetchmode how the resulting array should be indexed 301 * @param int $rownum the row number to fetch (0 = first row) 302 * 303 * @return mixed DB_OK on success, NULL when the end of a result set is 304 * reached or on failure 305 * 306 * @see DB_result::fetchInto() 307 */ 308 function fetchInto($result, &$arr, $fetchmode, $rownum = null) 309 { 310 if ($rownum !== null) { 311 if (!@msql_data_seek($result, $rownum)) { 312 return null; 313 } 314 } 315 if ($fetchmode & DB_FETCHMODE_ASSOC) { 316 $arr = @msql_fetch_array($result, MSQL_ASSOC); 317 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { 318 $arr = array_change_key_case($arr, CASE_LOWER); 319 } 320 } else { 321 $arr = @msql_fetch_row($result); 322 } 323 if (!$arr) { 324 return null; 325 } 326 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 327 $this->_rtrimArrayValues($arr); 328 } 329 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 330 $this->_convertNullArrayValuesToEmpty($arr); 331 } 332 return DB_OK; 333 } 334 335 // }}} 336 // {{{ freeResult() 337 338 /** 339 * Deletes the result set and frees the memory occupied by the result set 340 * 341 * This method is not meant to be called directly. Use 342 * DB_result::free() instead. It can't be declared "protected" 343 * because DB_result is a separate object. 344 * 345 * @param resource $result PHP's query result resource 346 * 347 * @return bool TRUE on success, FALSE if $result is invalid 348 * 349 * @see DB_result::free() 350 */ 351 function freeResult($result) 352 { 353 return is_resource($result) ? msql_free_result($result) : false; 354 } 355 356 // }}} 357 // {{{ numCols() 358 359 /** 360 * Gets the number of columns in a result set 361 * 362 * This method is not meant to be called directly. Use 363 * DB_result::numCols() instead. It can't be declared "protected" 364 * because DB_result is a separate object. 365 * 366 * @param resource $result PHP's query result resource 367 * 368 * @return int the number of columns. A DB_Error object on failure. 369 * 370 * @see DB_result::numCols() 371 */ 372 function numCols($result) 373 { 374 $cols = @msql_num_fields($result); 375 if (!$cols) { 376 return $this->msqlRaiseError(); 377 } 378 return $cols; 379 } 380 381 // }}} 382 // {{{ numRows() 383 384 /** 385 * Gets the number of rows in a result set 386 * 387 * This method is not meant to be called directly. Use 388 * DB_result::numRows() instead. It can't be declared "protected" 389 * because DB_result is a separate object. 390 * 391 * @param resource $result PHP's query result resource 392 * 393 * @return int the number of rows. A DB_Error object on failure. 394 * 395 * @see DB_result::numRows() 396 */ 397 function numRows($result) 398 { 399 $rows = @msql_num_rows($result); 400 if ($rows === false) { 401 return $this->msqlRaiseError(); 402 } 403 return $rows; 404 } 405 406 // }}} 407 // {{{ affected() 408 409 /** 410 * Determines the number of rows affected by a data maniuplation query 411 * 412 * 0 is returned for queries that don't manipulate data. 413 * 414 * @return int the number of rows. A DB_Error object on failure. 415 */ 416 function affectedRows() 417 { 418 if (!$this->_result) { 419 return 0; 420 } 421 return msql_affected_rows($this->_result); 422 } 423 424 // }}} 425 // {{{ nextId() 426 427 /** 428 * Returns the next free id in a sequence 429 * 430 * @param string $seq_name name of the sequence 431 * @param boolean $ondemand when true, the seqence is automatically 432 * created if it does not exist 433 * 434 * @return int the next id number in the sequence. 435 * A DB_Error object on failure. 436 * 437 * @see DB_common::nextID(), DB_common::getSequenceName(), 438 * DB_msql::createSequence(), DB_msql::dropSequence() 439 */ 440 function nextId($seq_name, $ondemand = true) 441 { 442 $seqname = $this->getSequenceName($seq_name); 443 $repeat = false; 444 do { 445 $this->pushErrorHandling(PEAR_ERROR_RETURN); 446 $result =& $this->query("SELECT _seq FROM $seqname}"); 447 $this->popErrorHandling(); 448 if ($ondemand && DB::isError($result) && 449 $result->getCode() == DB_ERROR_NOSUCHTABLE) { 450 $repeat = true; 451 $this->pushErrorHandling(PEAR_ERROR_RETURN); 452 $result = $this->createSequence($seq_name); 453 $this->popErrorHandling(); 454 if (DB::isError($result)) { 455 return $this->raiseError($result); 456 } 457 } else { 458 $repeat = false; 459 } 460 } while ($repeat); 461 if (DB::isError($result)) { 462 return $this->raiseError($result); 463 } 464 $arr = $result->fetchRow(DB_FETCHMODE_ORDERED); 465 $result->free(); 466 return $arr[0]; 467 } 468 469 // }}} 470 // {{{ createSequence() 471 472 /** 473 * Creates a new sequence 474 * 475 * Also creates a new table to associate the sequence with. Uses 476 * a separate table to ensure portability with other drivers. 477 * 478 * @param string $seq_name name of the new sequence 479 * 480 * @return int DB_OK on success. A DB_Error object on failure. 481 * 482 * @see DB_common::createSequence(), DB_common::getSequenceName(), 483 * DB_msql::nextID(), DB_msql::dropSequence() 484 */ 485 function createSequence($seq_name) 486 { 487 $seqname = $this->getSequenceName($seq_name); 488 $res = $this->query('CREATE TABLE ' . $seqname 489 . ' (id INTEGER NOT NULL)'); 490 if (DB::isError($res)) { 491 return $res; 492 } 493 $res = $this->query("CREATE SEQUENCE ON $seqname}"); 494 return $res; 495 } 496 497 // }}} 498 // {{{ dropSequence() 499 500 /** 501 * Deletes a sequence 502 * 503 * @param string $seq_name name of the sequence to be deleted 504 * 505 * @return int DB_OK on success. A DB_Error object on failure. 506 * 507 * @see DB_common::dropSequence(), DB_common::getSequenceName(), 508 * DB_msql::nextID(), DB_msql::createSequence() 509 */ 510 function dropSequence($seq_name) 511 { 512 return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); 513 } 514 515 // }}} 516 // {{{ quoteIdentifier() 517 518 /** 519 * mSQL does not support delimited identifiers 520 * 521 * @param string $str the identifier name to be quoted 522 * 523 * @return object a DB_Error object 524 * 525 * @see DB_common::quoteIdentifier() 526 * @since Method available since Release 1.7.0 527 */ 528 function quoteIdentifier($str) 529 { 530 return $this->raiseError(DB_ERROR_UNSUPPORTED); 531 } 532 533 // }}} 534 // {{{ quoteFloat() 535 536 /** 537 * Formats a float value for use within a query in a locale-independent 538 * manner. 539 * 540 * @param float the float value to be quoted. 541 * @return string the quoted string. 542 * @see DB_common::quoteSmart() 543 * @since Method available since release 1.7.8. 544 */ 545 function quoteFloat($float) { 546 return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); 547 } 548 549 // }}} 550 // {{{ escapeSimple() 551 552 /** 553 * Escapes a string according to the current DBMS's standards 554 * 555 * @param string $str the string to be escaped 556 * 557 * @return string the escaped string 558 * 559 * @see DB_common::quoteSmart() 560 * @since Method available since Release 1.7.0 561 */ 562 function escapeSimple($str) 563 { 564 return addslashes($str); 565 } 566 567 // }}} 568 // {{{ msqlRaiseError() 569 570 /** 571 * Produces a DB_Error object regarding the current problem 572 * 573 * @param int $errno if the error is being manually raised pass a 574 * DB_ERROR* constant here. If this isn't passed 575 * the error information gathered from the DBMS. 576 * 577 * @return object the DB_Error object 578 * 579 * @see DB_common::raiseError(), 580 * DB_msql::errorNative(), DB_msql::errorCode() 581 */ 582 function msqlRaiseError($errno = null) 583 { 584 $native = $this->errorNative(); 585 if ($errno === null) { 586 $errno = $this->errorCode($native); 587 } 588 return $this->raiseError($errno, null, null, null, $native); 589 } 590 591 // }}} 592 // {{{ errorNative() 593 594 /** 595 * Gets the DBMS' native error message produced by the last query 596 * 597 * @return string the DBMS' error message 598 */ 599 function errorNative() 600 { 601 return @msql_error(); 602 } 603 604 // }}} 605 // {{{ errorCode() 606 607 /** 608 * Determines PEAR::DB error code from the database's text error message 609 * 610 * @param string $errormsg the error message returned from the database 611 * 612 * @return integer the error number from a DB_ERROR* constant 613 */ 614 function errorCode($errormsg) 615 { 616 static $error_regexps; 617 618 // PHP 5.2+ prepends the function name to $php_errormsg, so we need 619 // this hack to work around it, per bug #9599. 620 $errormsg = preg_replace('/^msql[a-z_]+\(\): /', '', $errormsg); 621 622 if (!isset($error_regexps)) { 623 $error_regexps = array( 624 '/^Access to database denied/i' 625 => DB_ERROR_ACCESS_VIOLATION, 626 '/^Bad index name/i' 627 => DB_ERROR_ALREADY_EXISTS, 628 '/^Bad order field/i' 629 => DB_ERROR_SYNTAX, 630 '/^Bad type for comparison/i' 631 => DB_ERROR_SYNTAX, 632 '/^Can\'t perform LIKE on/i' 633 => DB_ERROR_SYNTAX, 634 '/^Can\'t use TEXT fields in LIKE comparison/i' 635 => DB_ERROR_SYNTAX, 636 '/^Couldn\'t create temporary table/i' 637 => DB_ERROR_CANNOT_CREATE, 638 '/^Error creating table file/i' 639 => DB_ERROR_CANNOT_CREATE, 640 '/^Field .* cannot be null$/i' 641 => DB_ERROR_CONSTRAINT_NOT_NULL, 642 '/^Index (field|condition) .* cannot be null$/i' 643 => DB_ERROR_SYNTAX, 644 '/^Invalid date format/i' 645 => DB_ERROR_INVALID_DATE, 646 '/^Invalid time format/i' 647 => DB_ERROR_INVALID, 648 '/^Literal value for .* is wrong type$/i' 649 => DB_ERROR_INVALID_NUMBER, 650 '/^No Database Selected/i' 651 => DB_ERROR_NODBSELECTED, 652 '/^No value specified for field/i' 653 => DB_ERROR_VALUE_COUNT_ON_ROW, 654 '/^Non unique value for unique index/i' 655 => DB_ERROR_CONSTRAINT, 656 '/^Out of memory for temporary table/i' 657 => DB_ERROR_CANNOT_CREATE, 658 '/^Permission denied/i' 659 => DB_ERROR_ACCESS_VIOLATION, 660 '/^Reference to un-selected table/i' 661 => DB_ERROR_SYNTAX, 662 '/^syntax error/i' 663 => DB_ERROR_SYNTAX, 664 '/^Table .* exists$/i' 665 => DB_ERROR_ALREADY_EXISTS, 666 '/^Unknown database/i' 667 => DB_ERROR_NOSUCHDB, 668 '/^Unknown field/i' 669 => DB_ERROR_NOSUCHFIELD, 670 '/^Unknown (index|system variable)/i' 671 => DB_ERROR_NOT_FOUND, 672 '/^Unknown table/i' 673 => DB_ERROR_NOSUCHTABLE, 674 '/^Unqualified field/i' 675 => DB_ERROR_SYNTAX, 676 ); 677 } 678 679 foreach ($error_regexps as $regexp => $code) { 680 if (preg_match($regexp, $errormsg)) { 681 return $code; 682 } 683 } 684 return DB_ERROR; 685 } 686 687 // }}} 688 // {{{ tableInfo() 689 690 /** 691 * Returns information about a table or a result set 692 * 693 * @param object|string $result DB_result object from a query or a 694 * string containing the name of a table. 695 * While this also accepts a query result 696 * resource identifier, this behavior is 697 * deprecated. 698 * @param int $mode a valid tableInfo mode 699 * 700 * @return array an associative array with the information requested. 701 * A DB_Error object on failure. 702 * 703 * @see DB_common::setOption() 704 */ 705 function tableInfo($result, $mode = null) 706 { 707 if (is_string($result)) { 708 /* 709 * Probably received a table name. 710 * Create a result resource identifier. 711 */ 712 $id = @msql_query("SELECT * FROM $result", 713 $this->connection); 714 $got_string = true; 715 } elseif (isset($result->result)) { 716 /* 717 * Probably received a result object. 718 * Extract the result resource identifier. 719 */ 720 $id = $result->result; 721 $got_string = false; 722 } else { 723 /* 724 * Probably received a result resource identifier. 725 * Copy it. 726 * Deprecated. Here for compatibility only. 727 */ 728 $id = $result; 729 $got_string = false; 730 } 731 732 if (!is_resource($id)) { 733 return $this->raiseError(DB_ERROR_NEED_MORE_DATA); 734 } 735 736 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 737 $case_func = 'strtolower'; 738 } else { 739 $case_func = 'strval'; 740 } 741 742 $count = @msql_num_fields($id); 743 $res = array(); 744 745 if ($mode) { 746 $res['num_fields'] = $count; 747 } 748 749 for ($i = 0; $i < $count; $i++) { 750 $tmp = @msql_fetch_field($id); 751 752 $flags = ''; 753 if ($tmp->not_null) { 754 $flags .= 'not_null '; 755 } 756 if ($tmp->unique) { 757 $flags .= 'unique_key '; 758 } 759 $flags = trim($flags); 760 761 $res[$i] = array( 762 'table' => $case_func($tmp->table), 763 'name' => $case_func($tmp->name), 764 'type' => $tmp->type, 765 'len' => msql_field_len($id, $i), 766 'flags' => $flags, 767 ); 768 769 if ($mode & DB_TABLEINFO_ORDER) { 770 $res['order'][$res[$i]['name']] = $i; 771 } 772 if ($mode & DB_TABLEINFO_ORDERTABLE) { 773 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 774 } 775 } 776 777 // free the result only if we were called on a table 778 if ($got_string) { 779 @msql_free_result($id); 780 } 781 return $res; 782 } 783 784 // }}} 785 // {{{ getSpecialQuery() 786 787 /** 788 * Obtain a list of a given type of objects 789 * 790 * @param string $type the kind of objects you want to retrieve 791 * 792 * @return array the array containing the list of objects requested 793 * 794 * @access protected 795 * @see DB_common::getListOf() 796 */ 797 function getSpecialQuery($type) 798 { 799 switch ($type) { 800 case 'databases': 801 $id = @msql_list_dbs($this->connection); 802 break; 803 case 'tables': 804 $id = @msql_list_tables($this->dsn['database'], 805 $this->connection); 806 break; 807 default: 808 return null; 809 } 810 if (!$id) { 811 return $this->msqlRaiseError(); 812 } 813 $out = array(); 814 while ($row = @msql_fetch_row($id)) { 815 $out[] = $row[0]; 816 } 817 return $out; 818 } 819 820 // }}} 821 822 } 823 824 /* 825 * Local variables: 826 * tab-width: 4 827 * c-basic-offset: 4 828 * End: 829 */ 830 831 ?>
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 |