[ 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 mysqli extension 7 * for interacting with MySQL 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 Daniel Convissor <danielc@php.net> 20 * @copyright 1997-2005 The PHP Group 21 * @license http://www.php.net/license/3_0.txt PHP License 3.0 22 * @version CVS: $Id: mysqli.php,v 1.78 2007/01/12 03:11:17 aharvey Exp $ 23 * @link http://pear.php.net/package/DB 24 */ 25 26 /** 27 * Obtain the DB_common class so it can be extended from 28 */ 29 require_once 'DB/common.php'; 30 31 /** 32 * The methods PEAR DB uses to interact with PHP's mysqli extension 33 * for interacting with MySQL databases 34 * 35 * This is for MySQL versions 4.1 and above. Requires PHP 5. 36 * 37 * Note that persistent connections no longer exist. 38 * 39 * These methods overload the ones declared in DB_common. 40 * 41 * @category Database 42 * @package DB 43 * @author Daniel Convissor <danielc@php.net> 44 * @copyright 1997-2005 The PHP Group 45 * @license http://www.php.net/license/3_0.txt PHP License 3.0 46 * @version Release: 1.7.9 47 * @link http://pear.php.net/package/DB 48 * @since Class functional since Release 1.6.3 49 */ 50 class DB_mysqli extends DB_common 51 { 52 // {{{ properties 53 54 /** 55 * The DB driver type (mysql, oci8, odbc, etc.) 56 * @var string 57 */ 58 var $phptype = 'mysqli'; 59 60 /** 61 * The database syntax variant to be used (db2, access, etc.), if any 62 * @var string 63 */ 64 var $dbsyntax = 'mysqli'; 65 66 /** 67 * The capabilities of this DB implementation 68 * 69 * The 'new_link' element contains the PHP version that first provided 70 * new_link support for this DBMS. Contains false if it's unsupported. 71 * 72 * Meaning of the 'limit' element: 73 * + 'emulate' = emulate with fetch row by number 74 * + 'alter' = alter the query 75 * + false = skip rows 76 * 77 * @var array 78 */ 79 var $features = array( 80 'limit' => 'alter', 81 'new_link' => false, 82 'numrows' => true, 83 'pconnect' => false, 84 'prepare' => false, 85 'ssl' => true, 86 'transactions' => true, 87 ); 88 89 /** 90 * A mapping of native error codes to DB error codes 91 * @var array 92 */ 93 var $errorcode_map = array( 94 1004 => DB_ERROR_CANNOT_CREATE, 95 1005 => DB_ERROR_CANNOT_CREATE, 96 1006 => DB_ERROR_CANNOT_CREATE, 97 1007 => DB_ERROR_ALREADY_EXISTS, 98 1008 => DB_ERROR_CANNOT_DROP, 99 1022 => DB_ERROR_ALREADY_EXISTS, 100 1044 => DB_ERROR_ACCESS_VIOLATION, 101 1046 => DB_ERROR_NODBSELECTED, 102 1048 => DB_ERROR_CONSTRAINT, 103 1049 => DB_ERROR_NOSUCHDB, 104 1050 => DB_ERROR_ALREADY_EXISTS, 105 1051 => DB_ERROR_NOSUCHTABLE, 106 1054 => DB_ERROR_NOSUCHFIELD, 107 1061 => DB_ERROR_ALREADY_EXISTS, 108 1062 => DB_ERROR_ALREADY_EXISTS, 109 1064 => DB_ERROR_SYNTAX, 110 1091 => DB_ERROR_NOT_FOUND, 111 1100 => DB_ERROR_NOT_LOCKED, 112 1136 => DB_ERROR_VALUE_COUNT_ON_ROW, 113 1142 => DB_ERROR_ACCESS_VIOLATION, 114 1146 => DB_ERROR_NOSUCHTABLE, 115 1216 => DB_ERROR_CONSTRAINT, 116 1217 => DB_ERROR_CONSTRAINT, 117 1356 => DB_ERROR_DIVZERO, 118 1451 => DB_ERROR_CONSTRAINT, 119 1452 => DB_ERROR_CONSTRAINT, 120 ); 121 122 /** 123 * The raw database connection created by PHP 124 * @var resource 125 */ 126 var $connection; 127 128 /** 129 * The DSN information for connecting to a database 130 * @var array 131 */ 132 var $dsn = array(); 133 134 135 /** 136 * Should data manipulation queries be committed automatically? 137 * @var bool 138 * @access private 139 */ 140 var $autocommit = true; 141 142 /** 143 * The quantity of transactions begun 144 * 145 * {@internal While this is private, it can't actually be designated 146 * private in PHP 5 because it is directly accessed in the test suite.}} 147 * 148 * @var integer 149 * @access private 150 */ 151 var $transaction_opcount = 0; 152 153 /** 154 * The database specified in the DSN 155 * 156 * It's a fix to allow calls to different databases in the same script. 157 * 158 * @var string 159 * @access private 160 */ 161 var $_db = ''; 162 163 /** 164 * Array for converting MYSQLI_*_FLAG constants to text values 165 * @var array 166 * @access public 167 * @since Property available since Release 1.6.5 168 */ 169 var $mysqli_flags = array( 170 MYSQLI_NOT_NULL_FLAG => 'not_null', 171 MYSQLI_PRI_KEY_FLAG => 'primary_key', 172 MYSQLI_UNIQUE_KEY_FLAG => 'unique_key', 173 MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key', 174 MYSQLI_BLOB_FLAG => 'blob', 175 MYSQLI_UNSIGNED_FLAG => 'unsigned', 176 MYSQLI_ZEROFILL_FLAG => 'zerofill', 177 MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment', 178 MYSQLI_TIMESTAMP_FLAG => 'timestamp', 179 MYSQLI_SET_FLAG => 'set', 180 // MYSQLI_NUM_FLAG => 'numeric', // unnecessary 181 // MYSQLI_PART_KEY_FLAG => 'multiple_key', // duplicatvie 182 MYSQLI_GROUP_FLAG => 'group_by' 183 ); 184 185 /** 186 * Array for converting MYSQLI_TYPE_* constants to text values 187 * @var array 188 * @access public 189 * @since Property available since Release 1.6.5 190 */ 191 var $mysqli_types = array( 192 MYSQLI_TYPE_DECIMAL => 'decimal', 193 246 => 'decimal', 194 MYSQLI_TYPE_TINY => 'tinyint', 195 MYSQLI_TYPE_SHORT => 'int', 196 MYSQLI_TYPE_LONG => 'int', 197 MYSQLI_TYPE_FLOAT => 'float', 198 MYSQLI_TYPE_DOUBLE => 'double', 199 // MYSQLI_TYPE_NULL => 'DEFAULT NULL', // let flags handle it 200 MYSQLI_TYPE_TIMESTAMP => 'timestamp', 201 MYSQLI_TYPE_LONGLONG => 'bigint', 202 MYSQLI_TYPE_INT24 => 'mediumint', 203 MYSQLI_TYPE_DATE => 'date', 204 MYSQLI_TYPE_TIME => 'time', 205 MYSQLI_TYPE_DATETIME => 'datetime', 206 MYSQLI_TYPE_YEAR => 'year', 207 MYSQLI_TYPE_NEWDATE => 'date', 208 MYSQLI_TYPE_ENUM => 'enum', 209 MYSQLI_TYPE_SET => 'set', 210 MYSQLI_TYPE_TINY_BLOB => 'tinyblob', 211 MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob', 212 MYSQLI_TYPE_LONG_BLOB => 'longblob', 213 MYSQLI_TYPE_BLOB => 'blob', 214 MYSQLI_TYPE_VAR_STRING => 'varchar', 215 MYSQLI_TYPE_STRING => 'char', 216 MYSQLI_TYPE_GEOMETRY => 'geometry', 217 ); 218 219 220 // }}} 221 // {{{ constructor 222 223 /** 224 * This constructor calls <kbd>$this->DB_common()</kbd> 225 * 226 * @return void 227 */ 228 function DB_mysqli() 229 { 230 $this->DB_common(); 231 } 232 233 // }}} 234 // {{{ connect() 235 236 /** 237 * Connect to the database server, log in and open the database 238 * 239 * Don't call this method directly. Use DB::connect() instead. 240 * 241 * PEAR DB's mysqli driver supports the following extra DSN options: 242 * + When the 'ssl' $option passed to DB::connect() is true: 243 * + key The path to the key file. 244 * + cert The path to the certificate file. 245 * + ca The path to the certificate authority file. 246 * + capath The path to a directory that contains trusted SSL 247 * CA certificates in pem format. 248 * + cipher The list of allowable ciphers for SSL encryption. 249 * 250 * Example of how to connect using SSL: 251 * <code> 252 * require_once 'DB.php'; 253 * 254 * $dsn = array( 255 * 'phptype' => 'mysqli', 256 * 'username' => 'someuser', 257 * 'password' => 'apasswd', 258 * 'hostspec' => 'localhost', 259 * 'database' => 'thedb', 260 * 'key' => 'client-key.pem', 261 * 'cert' => 'client-cert.pem', 262 * 'ca' => 'cacert.pem', 263 * 'capath' => '/path/to/ca/dir', 264 * 'cipher' => 'AES', 265 * ); 266 * 267 * $options = array( 268 * 'ssl' => true, 269 * ); 270 * 271 * $db =& DB::connect($dsn, $options); 272 * if (PEAR::isError($db)) { 273 * die($db->getMessage()); 274 * } 275 * </code> 276 * 277 * @param array $dsn the data source name 278 * @param bool $persistent should the connection be persistent? 279 * 280 * @return int DB_OK on success. A DB_Error object on failure. 281 */ 282 function connect($dsn, $persistent = false) 283 { 284 if (!PEAR::loadExtension('mysqli')) { 285 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 286 } 287 288 $this->dsn = $dsn; 289 if ($dsn['dbsyntax']) { 290 $this->dbsyntax = $dsn['dbsyntax']; 291 } 292 293 $ini = ini_get('track_errors'); 294 @ini_set('track_errors', 1); 295 $php_errormsg = ''; 296 297 if (((int) $this->getOption('ssl')) === 1) { 298 $init = mysqli_init(); 299 mysqli_ssl_set( 300 $init, 301 empty($dsn['key']) ? null : $dsn['key'], 302 empty($dsn['cert']) ? null : $dsn['cert'], 303 empty($dsn['ca']) ? null : $dsn['ca'], 304 empty($dsn['capath']) ? null : $dsn['capath'], 305 empty($dsn['cipher']) ? null : $dsn['cipher'] 306 ); 307 if ($this->connection = @mysqli_real_connect( 308 $init, 309 $dsn['hostspec'], 310 $dsn['username'], 311 $dsn['password'], 312 $dsn['database'], 313 $dsn['port'], 314 $dsn['socket'])) 315 { 316 $this->connection = $init; 317 } 318 } else { 319 $this->connection = @mysqli_connect( 320 $dsn['hostspec'], 321 $dsn['username'], 322 $dsn['password'], 323 $dsn['database'], 324 $dsn['port'], 325 $dsn['socket'] 326 ); 327 } 328 329 @ini_set('track_errors', $ini); 330 331 if (!$this->connection) { 332 if (($err = @mysqli_connect_error()) != '') { 333 return $this->raiseError(DB_ERROR_CONNECT_FAILED, 334 null, null, null, 335 $err); 336 } else { 337 return $this->raiseError(DB_ERROR_CONNECT_FAILED, 338 null, null, null, 339 $php_errormsg); 340 } 341 } 342 343 if ($dsn['database']) { 344 $this->_db = $dsn['database']; 345 } 346 347 return DB_OK; 348 } 349 350 // }}} 351 // {{{ disconnect() 352 353 /** 354 * Disconnects from the database server 355 * 356 * @return bool TRUE on success, FALSE on failure 357 */ 358 function disconnect() 359 { 360 $ret = @mysqli_close($this->connection); 361 $this->connection = null; 362 return $ret; 363 } 364 365 // }}} 366 // {{{ simpleQuery() 367 368 /** 369 * Sends a query to the database server 370 * 371 * @param string the SQL query string 372 * 373 * @return mixed + a PHP result resrouce for successful SELECT queries 374 * + the DB_OK constant for other successful queries 375 * + a DB_Error object on failure 376 */ 377 function simpleQuery($query) 378 { 379 $ismanip = $this->_checkManip($query); 380 $this->last_query = $query; 381 $query = $this->modifyQuery($query); 382 if ($this->_db) { 383 if (!@mysqli_select_db($this->connection, $this->_db)) { 384 return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); 385 } 386 } 387 if (!$this->autocommit && $ismanip) { 388 if ($this->transaction_opcount == 0) { 389 $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=0'); 390 $result = @mysqli_query($this->connection, 'BEGIN'); 391 if (!$result) { 392 return $this->mysqliRaiseError(); 393 } 394 } 395 $this->transaction_opcount++; 396 } 397 $result = @mysqli_query($this->connection, $query); 398 if (!$result) { 399 return $this->mysqliRaiseError(); 400 } 401 if (is_object($result)) { 402 return $result; 403 } 404 return DB_OK; 405 } 406 407 // }}} 408 // {{{ nextResult() 409 410 /** 411 * Move the internal mysql result pointer to the next available result. 412 * 413 * This method has not been implemented yet. 414 * 415 * @param resource $result a valid sql result resource 416 * @return false 417 * @access public 418 */ 419 function nextResult($result) 420 { 421 return false; 422 } 423 424 // }}} 425 // {{{ fetchInto() 426 427 /** 428 * Places a row from the result set into the given array 429 * 430 * Formating of the array and the data therein are configurable. 431 * See DB_result::fetchInto() for more information. 432 * 433 * This method is not meant to be called directly. Use 434 * DB_result::fetchInto() instead. It can't be declared "protected" 435 * because DB_result is a separate object. 436 * 437 * @param resource $result the query result resource 438 * @param array $arr the referenced array to put the data in 439 * @param int $fetchmode how the resulting array should be indexed 440 * @param int $rownum the row number to fetch (0 = first row) 441 * 442 * @return mixed DB_OK on success, NULL when the end of a result set is 443 * reached or on failure 444 * 445 * @see DB_result::fetchInto() 446 */ 447 function fetchInto($result, &$arr, $fetchmode, $rownum = null) 448 { 449 if ($rownum !== null) { 450 if (!@mysqli_data_seek($result, $rownum)) { 451 return null; 452 } 453 } 454 if ($fetchmode & DB_FETCHMODE_ASSOC) { 455 $arr = @mysqli_fetch_array($result, MYSQLI_ASSOC); 456 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { 457 $arr = array_change_key_case($arr, CASE_LOWER); 458 } 459 } else { 460 $arr = @mysqli_fetch_row($result); 461 } 462 if (!$arr) { 463 return null; 464 } 465 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 466 /* 467 * Even though this DBMS already trims output, we do this because 468 * a field might have intentional whitespace at the end that 469 * gets removed by DB_PORTABILITY_RTRIM under another driver. 470 */ 471 $this->_rtrimArrayValues($arr); 472 } 473 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 474 $this->_convertNullArrayValuesToEmpty($arr); 475 } 476 return DB_OK; 477 } 478 479 // }}} 480 // {{{ freeResult() 481 482 /** 483 * Deletes the result set and frees the memory occupied by the result set 484 * 485 * This method is not meant to be called directly. Use 486 * DB_result::free() instead. It can't be declared "protected" 487 * because DB_result is a separate object. 488 * 489 * @param resource $result PHP's query result resource 490 * 491 * @return bool TRUE on success, FALSE if $result is invalid 492 * 493 * @see DB_result::free() 494 */ 495 function freeResult($result) 496 { 497 return is_resource($result) ? mysqli_free_result($result) : false; 498 } 499 500 // }}} 501 // {{{ numCols() 502 503 /** 504 * Gets the number of columns in a result set 505 * 506 * This method is not meant to be called directly. Use 507 * DB_result::numCols() instead. It can't be declared "protected" 508 * because DB_result is a separate object. 509 * 510 * @param resource $result PHP's query result resource 511 * 512 * @return int the number of columns. A DB_Error object on failure. 513 * 514 * @see DB_result::numCols() 515 */ 516 function numCols($result) 517 { 518 $cols = @mysqli_num_fields($result); 519 if (!$cols) { 520 return $this->mysqliRaiseError(); 521 } 522 return $cols; 523 } 524 525 // }}} 526 // {{{ numRows() 527 528 /** 529 * Gets the number of rows in a result set 530 * 531 * This method is not meant to be called directly. Use 532 * DB_result::numRows() instead. It can't be declared "protected" 533 * because DB_result is a separate object. 534 * 535 * @param resource $result PHP's query result resource 536 * 537 * @return int the number of rows. A DB_Error object on failure. 538 * 539 * @see DB_result::numRows() 540 */ 541 function numRows($result) 542 { 543 $rows = @mysqli_num_rows($result); 544 if ($rows === null) { 545 return $this->mysqliRaiseError(); 546 } 547 return $rows; 548 } 549 550 // }}} 551 // {{{ autoCommit() 552 553 /** 554 * Enables or disables automatic commits 555 * 556 * @param bool $onoff true turns it on, false turns it off 557 * 558 * @return int DB_OK on success. A DB_Error object if the driver 559 * doesn't support auto-committing transactions. 560 */ 561 function autoCommit($onoff = false) 562 { 563 // XXX if $this->transaction_opcount > 0, we should probably 564 // issue a warning here. 565 $this->autocommit = $onoff ? true : false; 566 return DB_OK; 567 } 568 569 // }}} 570 // {{{ commit() 571 572 /** 573 * Commits the current transaction 574 * 575 * @return int DB_OK on success. A DB_Error object on failure. 576 */ 577 function commit() 578 { 579 if ($this->transaction_opcount > 0) { 580 if ($this->_db) { 581 if (!@mysqli_select_db($this->connection, $this->_db)) { 582 return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); 583 } 584 } 585 $result = @mysqli_query($this->connection, 'COMMIT'); 586 $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1'); 587 $this->transaction_opcount = 0; 588 if (!$result) { 589 return $this->mysqliRaiseError(); 590 } 591 } 592 return DB_OK; 593 } 594 595 // }}} 596 // {{{ rollback() 597 598 /** 599 * Reverts the current transaction 600 * 601 * @return int DB_OK on success. A DB_Error object on failure. 602 */ 603 function rollback() 604 { 605 if ($this->transaction_opcount > 0) { 606 if ($this->_db) { 607 if (!@mysqli_select_db($this->connection, $this->_db)) { 608 return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); 609 } 610 } 611 $result = @mysqli_query($this->connection, 'ROLLBACK'); 612 $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1'); 613 $this->transaction_opcount = 0; 614 if (!$result) { 615 return $this->mysqliRaiseError(); 616 } 617 } 618 return DB_OK; 619 } 620 621 // }}} 622 // {{{ affectedRows() 623 624 /** 625 * Determines the number of rows affected by a data maniuplation query 626 * 627 * 0 is returned for queries that don't manipulate data. 628 * 629 * @return int the number of rows. A DB_Error object on failure. 630 */ 631 function affectedRows() 632 { 633 if ($this->_last_query_manip) { 634 return @mysqli_affected_rows($this->connection); 635 } else { 636 return 0; 637 } 638 } 639 640 // }}} 641 // {{{ nextId() 642 643 /** 644 * Returns the next free id in a sequence 645 * 646 * @param string $seq_name name of the sequence 647 * @param boolean $ondemand when true, the seqence is automatically 648 * created if it does not exist 649 * 650 * @return int the next id number in the sequence. 651 * A DB_Error object on failure. 652 * 653 * @see DB_common::nextID(), DB_common::getSequenceName(), 654 * DB_mysqli::createSequence(), DB_mysqli::dropSequence() 655 */ 656 function nextId($seq_name, $ondemand = true) 657 { 658 $seqname = $this->getSequenceName($seq_name); 659 do { 660 $repeat = 0; 661 $this->pushErrorHandling(PEAR_ERROR_RETURN); 662 $result = $this->query('UPDATE ' . $seqname 663 . ' SET id = LAST_INSERT_ID(id + 1)'); 664 $this->popErrorHandling(); 665 if ($result === DB_OK) { 666 // COMMON CASE 667 $id = @mysqli_insert_id($this->connection); 668 if ($id != 0) { 669 return $id; 670 } 671 672 // EMPTY SEQ TABLE 673 // Sequence table must be empty for some reason, 674 // so fill it and return 1 675 // Obtain a user-level lock 676 $result = $this->getOne('SELECT GET_LOCK(' 677 . "'$seqname}_lock', 10)"); 678 if (DB::isError($result)) { 679 return $this->raiseError($result); 680 } 681 if ($result == 0) { 682 return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED); 683 } 684 685 // add the default value 686 $result = $this->query('REPLACE INTO ' . $seqname 687 . ' (id) VALUES (0)'); 688 if (DB::isError($result)) { 689 return $this->raiseError($result); 690 } 691 692 // Release the lock 693 $result = $this->getOne('SELECT RELEASE_LOCK(' 694 . "'$seqname}_lock')"); 695 if (DB::isError($result)) { 696 return $this->raiseError($result); 697 } 698 // We know what the result will be, so no need to try again 699 return 1; 700 701 } elseif ($ondemand && DB::isError($result) && 702 $result->getCode() == DB_ERROR_NOSUCHTABLE) 703 { 704 // ONDEMAND TABLE CREATION 705 $result = $this->createSequence($seq_name); 706 707 // Since createSequence initializes the ID to be 1, 708 // we do not need to retrieve the ID again (or we will get 2) 709 if (DB::isError($result)) { 710 return $this->raiseError($result); 711 } else { 712 // First ID of a newly created sequence is 1 713 return 1; 714 } 715 716 } elseif (DB::isError($result) && 717 $result->getCode() == DB_ERROR_ALREADY_EXISTS) 718 { 719 // BACKWARDS COMPAT 720 // see _BCsequence() comment 721 $result = $this->_BCsequence($seqname); 722 if (DB::isError($result)) { 723 return $this->raiseError($result); 724 } 725 $repeat = 1; 726 } 727 } while ($repeat); 728 729 return $this->raiseError($result); 730 } 731 732 /** 733 * Creates a new sequence 734 * 735 * @param string $seq_name name of the new sequence 736 * 737 * @return int DB_OK on success. A DB_Error object on failure. 738 * 739 * @see DB_common::createSequence(), DB_common::getSequenceName(), 740 * DB_mysqli::nextID(), DB_mysqli::dropSequence() 741 */ 742 function createSequence($seq_name) 743 { 744 $seqname = $this->getSequenceName($seq_name); 745 $res = $this->query('CREATE TABLE ' . $seqname 746 . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,' 747 . ' PRIMARY KEY(id))'); 748 if (DB::isError($res)) { 749 return $res; 750 } 751 // insert yields value 1, nextId call will generate ID 2 752 return $this->query("INSERT INTO $seqname} (id) VALUES (0)"); 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_mysql::nextID(), DB_mysql::createSequence() 767 */ 768 function dropSequence($seq_name) 769 { 770 return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); 771 } 772 773 // }}} 774 // {{{ _BCsequence() 775 776 /** 777 * Backwards compatibility with old sequence emulation implementation 778 * (clean up the dupes) 779 * 780 * @param string $seqname the sequence name to clean up 781 * 782 * @return bool true on success. A DB_Error object on failure. 783 * 784 * @access private 785 */ 786 function _BCsequence($seqname) 787 { 788 // Obtain a user-level lock... this will release any previous 789 // application locks, but unlike LOCK TABLES, it does not abort 790 // the current transaction and is much less frequently used. 791 $result = $this->getOne("SELECT GET_LOCK('$seqname}_lock',10)"); 792 if (DB::isError($result)) { 793 return $result; 794 } 795 if ($result == 0) { 796 // Failed to get the lock, can't do the conversion, bail 797 // with a DB_ERROR_NOT_LOCKED error 798 return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED); 799 } 800 801 $highest_id = $this->getOne("SELECT MAX(id) FROM $seqname}"); 802 if (DB::isError($highest_id)) { 803 return $highest_id; 804 } 805 806 // This should kill all rows except the highest 807 // We should probably do something if $highest_id isn't 808 // numeric, but I'm at a loss as how to handle that... 809 $result = $this->query('DELETE FROM ' . $seqname 810 . " WHERE id <> $highest_id"); 811 if (DB::isError($result)) { 812 return $result; 813 } 814 815 // If another thread has been waiting for this lock, 816 // it will go thru the above procedure, but will have no 817 // real effect 818 $result = $this->getOne("SELECT RELEASE_LOCK('$seqname}_lock')"); 819 if (DB::isError($result)) { 820 return $result; 821 } 822 return true; 823 } 824 825 // }}} 826 // {{{ quoteIdentifier() 827 828 /** 829 * Quotes a string so it can be safely used as a table or column name 830 * (WARNING: using names that require this is a REALLY BAD IDEA) 831 * 832 * WARNING: Older versions of MySQL can't handle the backtick 833 * character (<kbd>`</kbd>) in table or column names. 834 * 835 * @param string $str identifier name to be quoted 836 * 837 * @return string quoted identifier string 838 * 839 * @see DB_common::quoteIdentifier() 840 * @since Method available since Release 1.6.0 841 */ 842 function quoteIdentifier($str) 843 { 844 return '`' . str_replace('`', '``', $str) . '`'; 845 } 846 847 // }}} 848 // {{{ escapeSimple() 849 850 /** 851 * Escapes a string according to the current DBMS's standards 852 * 853 * @param string $str the string to be escaped 854 * 855 * @return string the escaped string 856 * 857 * @see DB_common::quoteSmart() 858 * @since Method available since Release 1.6.0 859 */ 860 function escapeSimple($str) 861 { 862 return @mysqli_real_escape_string($this->connection, $str); 863 } 864 865 // }}} 866 // {{{ modifyLimitQuery() 867 868 /** 869 * Adds LIMIT clauses to a query string according to current DBMS standards 870 * 871 * @param string $query the query to modify 872 * @param int $from the row to start to fetching (0 = the first row) 873 * @param int $count the numbers of rows to fetch 874 * @param mixed $params array, string or numeric data to be used in 875 * execution of the statement. Quantity of items 876 * passed must match quantity of placeholders in 877 * query: meaning 1 placeholder for non-array 878 * parameters or 1 placeholder per array element. 879 * 880 * @return string the query string with LIMIT clauses added 881 * 882 * @access protected 883 */ 884 function modifyLimitQuery($query, $from, $count, $params = array()) 885 { 886 if (DB::isManip($query) || $this->_next_query_manip) { 887 return $query . " LIMIT $count"; 888 } else { 889 return $query . " LIMIT $from, $count"; 890 } 891 } 892 893 // }}} 894 // {{{ mysqliRaiseError() 895 896 /** 897 * Produces a DB_Error object regarding the current problem 898 * 899 * @param int $errno if the error is being manually raised pass a 900 * DB_ERROR* constant here. If this isn't passed 901 * the error information gathered from the DBMS. 902 * 903 * @return object the DB_Error object 904 * 905 * @see DB_common::raiseError(), 906 * DB_mysqli::errorNative(), DB_common::errorCode() 907 */ 908 function mysqliRaiseError($errno = null) 909 { 910 if ($errno === null) { 911 if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { 912 $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT; 913 $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL; 914 $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT; 915 } else { 916 // Doing this in case mode changes during runtime. 917 $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS; 918 $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT; 919 $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS; 920 } 921 $errno = $this->errorCode(mysqli_errno($this->connection)); 922 } 923 return $this->raiseError($errno, null, null, null, 924 @mysqli_errno($this->connection) . ' ** ' . 925 @mysqli_error($this->connection)); 926 } 927 928 // }}} 929 // {{{ errorNative() 930 931 /** 932 * Gets the DBMS' native error code produced by the last query 933 * 934 * @return int the DBMS' error code 935 */ 936 function errorNative() 937 { 938 return @mysqli_errno($this->connection); 939 } 940 941 // }}} 942 // {{{ tableInfo() 943 944 /** 945 * Returns information about a table or a result set 946 * 947 * @param object|string $result DB_result object from a query or a 948 * string containing the name of a table. 949 * While this also accepts a query result 950 * resource identifier, this behavior is 951 * deprecated. 952 * @param int $mode a valid tableInfo mode 953 * 954 * @return array an associative array with the information requested. 955 * A DB_Error object on failure. 956 * 957 * @see DB_common::setOption() 958 */ 959 function tableInfo($result, $mode = null) 960 { 961 if (is_string($result)) { 962 /* 963 * Probably received a table name. 964 * Create a result resource identifier. 965 */ 966 $id = @mysqli_query($this->connection, 967 "SELECT * FROM $result LIMIT 0"); 968 $got_string = true; 969 } elseif (isset($result->result)) { 970 /* 971 * Probably received a result object. 972 * Extract the result resource identifier. 973 */ 974 $id = $result->result; 975 $got_string = false; 976 } else { 977 /* 978 * Probably received a result resource identifier. 979 * Copy it. 980 * Deprecated. Here for compatibility only. 981 */ 982 $id = $result; 983 $got_string = false; 984 } 985 986 if (!is_a($id, 'mysqli_result')) { 987 return $this->mysqliRaiseError(DB_ERROR_NEED_MORE_DATA); 988 } 989 990 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 991 $case_func = 'strtolower'; 992 } else { 993 $case_func = 'strval'; 994 } 995 996 $count = @mysqli_num_fields($id); 997 $res = array(); 998 999 if ($mode) { 1000 $res['num_fields'] = $count; 1001 } 1002 1003 for ($i = 0; $i < $count; $i++) { 1004 $tmp = @mysqli_fetch_field($id); 1005 1006 $flags = ''; 1007 foreach ($this->mysqli_flags as $const => $means) { 1008 if ($tmp->flags & $const) { 1009 $flags .= $means . ' '; 1010 } 1011 } 1012 if ($tmp->def) { 1013 $flags .= 'default_' . rawurlencode($tmp->def); 1014 } 1015 $flags = trim($flags); 1016 1017 $res[$i] = array( 1018 'table' => $case_func($tmp->table), 1019 'name' => $case_func($tmp->name), 1020 'type' => isset($this->mysqli_types[$tmp->type]) 1021 ? $this->mysqli_types[$tmp->type] 1022 : 'unknown', 1023 // http://bugs.php.net/?id=36579 1024 'len' => $tmp->length, 1025 'flags' => $flags, 1026 ); 1027 1028 if ($mode & DB_TABLEINFO_ORDER) { 1029 $res['order'][$res[$i]['name']] = $i; 1030 } 1031 if ($mode & DB_TABLEINFO_ORDERTABLE) { 1032 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 1033 } 1034 } 1035 1036 // free the result only if we were called on a table 1037 if ($got_string) { 1038 @mysqli_free_result($id); 1039 } 1040 return $res; 1041 } 1042 1043 // }}} 1044 // {{{ getSpecialQuery() 1045 1046 /** 1047 * Obtains the query string needed for listing a given type of objects 1048 * 1049 * @param string $type the kind of objects you want to retrieve 1050 * 1051 * @return string the SQL query string or null if the driver doesn't 1052 * support the object type requested 1053 * 1054 * @access protected 1055 * @see DB_common::getListOf() 1056 */ 1057 function getSpecialQuery($type) 1058 { 1059 switch ($type) { 1060 case 'tables': 1061 return 'SHOW TABLES'; 1062 case 'users': 1063 return 'SELECT DISTINCT User FROM mysql.user'; 1064 case 'databases': 1065 return 'SHOW DATABASES'; 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 |