[ Index ] |
|
Code source de SPIP Agora 1.4 |
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ 3 // +----------------------------------------------------------------------+ 4 // | PHP Version 4 | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1997-2004 The PHP Group | 7 // +----------------------------------------------------------------------+ 8 // | This source file is subject to version 2.02 of the PHP license, | 9 // | that is bundled with this package in the file LICENSE, and is | 10 // | available at through the world-wide-web at | 11 // | http://www.php.net/license/2_02.txt. | 12 // | If you did not receive a copy of the PHP license and are unable to | 13 // | obtain it through the world-wide-web, please send a note to | 14 // | license@php.net so we can mail you a copy immediately. | 15 // +----------------------------------------------------------------------+ 16 // | Author: Daniel Convissor <danielc@php.net> | 17 // +----------------------------------------------------------------------+ 18 // 19 // $Id: mysqli.php,v 1.31 2004/07/12 17:51:24 danielc Exp $ 20 21 22 // EXPERIMENTAL 23 24 25 require_once 'DB/common.php'; 26 27 /** 28 * Database independent query interface definition for PHP's mysqli 29 * extension. 30 * 31 * This is for MySQL versions 4.1 and above. Requires PHP 5. 32 * 33 * Note that persistent connections no longer exist. 34 * 35 * @package DB 36 * @version $Id: mysqli.php,v 1.31 2004/07/12 17:51:24 danielc Exp $ 37 * @category Database 38 * @author Daniel Convissor <danielc@php.net> 39 * @since Class functional since Release 1.6.3 40 */ 41 class DB_mysqli extends DB_common 42 { 43 // {{{ properties 44 45 var $connection; 46 var $phptype, $dbsyntax; 47 var $prepare_tokens = array(); 48 var $prepare_types = array(); 49 var $num_rows = array(); 50 var $transaction_opcount = 0; 51 var $autocommit = true; 52 var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */ 53 var $_db = false; 54 55 /** 56 * Array for converting MYSQLI_*_FLAG constants to text values 57 * @var array 58 * @access public 59 * @since Property available since Release 1.6.5 60 */ 61 var $mysqli_flags = array( 62 MYSQLI_NOT_NULL_FLAG => 'not_null', 63 MYSQLI_PRI_KEY_FLAG => 'primary_key', 64 MYSQLI_UNIQUE_KEY_FLAG => 'unique_key', 65 MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key', 66 MYSQLI_BLOB_FLAG => 'blob', 67 MYSQLI_UNSIGNED_FLAG => 'unsigned', 68 MYSQLI_ZEROFILL_FLAG => 'zerofill', 69 MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment', 70 MYSQLI_TIMESTAMP_FLAG => 'timestamp', 71 MYSQLI_SET_FLAG => 'set', 72 // MYSQLI_NUM_FLAG => 'numeric', // unnecessary 73 // MYSQLI_PART_KEY_FLAG => 'multiple_key', // duplicatvie 74 MYSQLI_GROUP_FLAG => 'group_by' 75 ); 76 77 /** 78 * Array for converting MYSQLI_TYPE_* constants to text values 79 * @var array 80 * @access public 81 * @since Property available since Release 1.6.5 82 */ 83 var $mysqli_types = array( 84 MYSQLI_TYPE_DECIMAL => 'decimal', 85 MYSQLI_TYPE_TINY => 'tinyint', 86 MYSQLI_TYPE_SHORT => 'int', 87 MYSQLI_TYPE_LONG => 'int', 88 MYSQLI_TYPE_FLOAT => 'float', 89 MYSQLI_TYPE_DOUBLE => 'double', 90 // MYSQLI_TYPE_NULL => 'DEFAULT NULL', // let flags handle it 91 MYSQLI_TYPE_TIMESTAMP => 'timestamp', 92 MYSQLI_TYPE_LONGLONG => 'bigint', 93 MYSQLI_TYPE_INT24 => 'mediumint', 94 MYSQLI_TYPE_DATE => 'date', 95 MYSQLI_TYPE_TIME => 'time', 96 MYSQLI_TYPE_DATETIME => 'datetime', 97 MYSQLI_TYPE_YEAR => 'year', 98 MYSQLI_TYPE_NEWDATE => 'date', 99 MYSQLI_TYPE_ENUM => 'enum', 100 MYSQLI_TYPE_SET => 'set', 101 MYSQLI_TYPE_TINY_BLOB => 'tinyblob', 102 MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob', 103 MYSQLI_TYPE_LONG_BLOB => 'longblob', 104 MYSQLI_TYPE_BLOB => 'blob', 105 MYSQLI_TYPE_VAR_STRING => 'varchar', 106 MYSQLI_TYPE_STRING => 'char', 107 MYSQLI_TYPE_GEOMETRY => 'geometry', 108 ); 109 110 // }}} 111 // {{{ constructor 112 113 /** 114 * DB_mysql constructor. 115 * 116 * @access public 117 */ 118 function DB_mysqli() 119 { 120 $this->DB_common(); 121 $this->phptype = 'mysqli'; 122 $this->dbsyntax = 'mysqli'; 123 $this->features = array( 124 'prepare' => false, 125 'ssl' => true, 126 'transactions' => true, 127 'limit' => 'alter' 128 ); 129 $this->errorcode_map = array( 130 1004 => DB_ERROR_CANNOT_CREATE, 131 1005 => DB_ERROR_CANNOT_CREATE, 132 1006 => DB_ERROR_CANNOT_CREATE, 133 1007 => DB_ERROR_ALREADY_EXISTS, 134 1008 => DB_ERROR_CANNOT_DROP, 135 1022 => DB_ERROR_ALREADY_EXISTS, 136 1046 => DB_ERROR_NODBSELECTED, 137 1048 => DB_ERROR_CONSTRAINT, 138 1050 => DB_ERROR_ALREADY_EXISTS, 139 1051 => DB_ERROR_NOSUCHTABLE, 140 1054 => DB_ERROR_NOSUCHFIELD, 141 1062 => DB_ERROR_ALREADY_EXISTS, 142 1064 => DB_ERROR_SYNTAX, 143 1100 => DB_ERROR_NOT_LOCKED, 144 1136 => DB_ERROR_VALUE_COUNT_ON_ROW, 145 1146 => DB_ERROR_NOSUCHTABLE, 146 1216 => DB_ERROR_CONSTRAINT, 147 1217 => DB_ERROR_CONSTRAINT, 148 ); 149 } 150 151 // }}} 152 // {{{ connect() 153 154 /** 155 * Connect to a database and log in as the specified user. 156 * 157 * @param string $dsn the data source name (see DB::parseDSN for syntax) 158 * @param boolean $persistent (optional) whether the connection should 159 * be persistent 160 * @return mixed DB_OK on success, a DB error on failure 161 * @access public 162 */ 163 function connect($dsninfo, $persistent = false) 164 { 165 if (!DB::assertExtension('mysqli')) { 166 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 167 } 168 169 $this->dsn = $dsninfo; 170 $conn = false; 171 @ini_set('track_errors', true); 172 173 if ($this->getOption('ssl') === true) { 174 $init = mysqli_init(); 175 mysqli_ssl_set( 176 $init, 177 empty($dsninfo['key']) ? null : $dsninfo['key'], 178 empty($dsninfo['cert']) ? null : $dsninfo['cert'], 179 empty($dsninfo['ca']) ? null : $dsninfo['ca'], 180 empty($dsninfo['capath']) ? null : $dsninfo['capath'], 181 empty($dsninfo['cipher']) ? null : $dsninfo['cipher'] 182 ); 183 if ($conn = @mysqli_real_connect($init, 184 $dsninfo['hostspec'], 185 $dsninfo['username'], 186 $dsninfo['password'], 187 $dsninfo['database'], 188 $dsninfo['port'], 189 $dsninfo['socket'])) 190 { 191 $conn = $init; 192 } 193 } else { 194 $conn = @mysqli_connect( 195 $dsninfo['hostspec'], 196 $dsninfo['username'], 197 $dsninfo['password'], 198 $dsninfo['database'], 199 $dsninfo['port'], 200 $dsninfo['socket'] 201 ); 202 } 203 204 @ini_restore('track_errors'); 205 206 if (!$conn) { 207 if (($err = @mysqli_connect_error()) != '') { 208 return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null, 209 null, $err); 210 } elseif (empty($php_errormsg)) { 211 return $this->raiseError(DB_ERROR_CONNECT_FAILED); 212 } else { 213 return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null, 214 null, $php_errormsg); 215 } 216 } 217 218 if ($dsninfo['database']) { 219 $this->_db = $dsninfo['database']; 220 } 221 222 $this->connection = $conn; 223 return DB_OK; 224 } 225 226 // }}} 227 // {{{ disconnect() 228 229 /** 230 * Log out and disconnect from the database. 231 * 232 * @return boolean true on success, false if not connected 233 * @access public 234 */ 235 function disconnect() 236 { 237 $ret = @mysqli_close($this->connection); 238 $this->connection = null; 239 return $ret; 240 } 241 242 // }}} 243 // {{{ simpleQuery() 244 245 /** 246 * Send a query to MySQL and return the results as a MySQL resource 247 * identifier. 248 * 249 * @param string $query the SQL query 250 * @return mixed a valid MySQL result for successful SELECT 251 * queries, DB_OK for other successful queries. 252 * A DB error is returned on failure. 253 * @access public 254 */ 255 function simpleQuery($query) 256 { 257 $ismanip = DB::isManip($query); 258 $this->last_query = $query; 259 $query = $this->modifyQuery($query); 260 if ($this->_db) { 261 if (!@mysqli_select_db($this->connection, $this->_db)) { 262 return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); 263 } 264 } 265 if (!$this->autocommit && $ismanip) { 266 if ($this->transaction_opcount == 0) { 267 $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=0'); 268 $result = @mysqli_query($this->connection, 'BEGIN'); 269 if (!$result) { 270 return $this->mysqlRaiseError(); 271 } 272 } 273 $this->transaction_opcount++; 274 } 275 $result = @mysqli_query($this->connection, $query); 276 if (!$result) { 277 return $this->mysqlRaiseError(); 278 } 279 # this next block is still sketchy.. 280 if (is_object($result)) { 281 $numrows = $this->numrows($result); 282 if (is_object($numrows)) { 283 return $numrows; 284 } 285 # need to come up with different means for next line 286 # since $result is object (int)$result won't fly... 287 // $this->num_rows[(int)$result] = $numrows; 288 return $result; 289 } 290 return DB_OK; 291 } 292 293 // }}} 294 // {{{ nextResult() 295 296 /** 297 * Move the internal mysql result pointer to the next available result. 298 * 299 * This method has not been implemented yet. 300 * 301 * @param resource $result a valid sql result resource 302 * @return false 303 * @access public 304 */ 305 function nextResult($result) 306 { 307 return false; 308 } 309 310 // }}} 311 // {{{ fetchInto() 312 313 /** 314 * Fetch a row and insert the data into an existing array. 315 * 316 * Formating of the array and the data therein are configurable. 317 * See DB_result::fetchInto() for more information. 318 * 319 * @param resource $result query result identifier 320 * @param array $arr (reference) array where data from the row 321 * should be placed 322 * @param int $fetchmode how the resulting array should be indexed 323 * @param int $rownum the row number to fetch 324 * 325 * @return mixed DB_OK on success, null when end of result set is 326 * reached or on failure 327 * 328 * @see DB_result::fetchInto() 329 * @access private 330 */ 331 function fetchInto($result, &$arr, $fetchmode, $rownum=null) 332 { 333 if ($rownum !== null) { 334 if (!@mysqli_data_seek($result, $rownum)) { 335 return null; 336 } 337 } 338 if ($fetchmode & DB_FETCHMODE_ASSOC) { 339 $arr = @mysqli_fetch_array($result, MYSQLI_ASSOC); 340 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { 341 $arr = array_change_key_case($arr, CASE_LOWER); 342 } 343 } else { 344 $arr = @mysqli_fetch_row($result); 345 } 346 if (!$arr) { 347 $errno = @mysqli_errno($this->connection); 348 if (!$errno) { 349 return null; 350 } 351 return $this->mysqlRaiseError($errno); 352 } 353 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 354 /* 355 * Even though this DBMS already trims output, we do this because 356 * a field might have intentional whitespace at the end that 357 * gets removed by DB_PORTABILITY_RTRIM under another driver. 358 */ 359 $this->_rtrimArrayValues($arr); 360 } 361 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 362 $this->_convertNullArrayValuesToEmpty($arr); 363 } 364 return DB_OK; 365 } 366 367 // }}} 368 // {{{ freeResult() 369 370 /** 371 * Free the internal resources associated with $result. 372 * 373 * @param resource $result MySQL result identifier 374 * @return bool true on success, false if $result is invalid 375 * @access public 376 */ 377 function freeResult($result) 378 { 379 # need to come up with different means for next line 380 # since $result is object (int)$result won't fly... 381 // unset($this->num_rows[(int)$result]); 382 return @mysqli_free_result($result); 383 } 384 385 // }}} 386 // {{{ numCols() 387 388 /** 389 * Get the number of columns in a result set. 390 * 391 * @param $result MySQL result identifier 392 * 393 * @access public 394 * 395 * @return int the number of columns per row in $result 396 */ 397 function numCols($result) 398 { 399 $cols = @mysqli_num_fields($result); 400 401 if (!$cols) { 402 return $this->mysqlRaiseError(); 403 } 404 405 return $cols; 406 } 407 408 // }}} 409 // {{{ numRows() 410 411 /** 412 * Get the number of rows in a result set. 413 * 414 * @param resource $result MySQL result identifier 415 * @return int the number of rows in $result 416 * @access public 417 */ 418 function numRows($result) 419 { 420 $rows = @mysqli_num_rows($result); 421 if ($rows === null) { 422 return $this->mysqlRaiseError(); 423 } 424 return $rows; 425 } 426 427 // }}} 428 // {{{ autoCommit() 429 430 /** 431 * Enable/disable automatic commits. 432 */ 433 function autoCommit($onoff = false) 434 { 435 // XXX if $this->transaction_opcount > 0, we should probably 436 // issue a warning here. 437 $this->autocommit = $onoff ? true : false; 438 return DB_OK; 439 } 440 441 // }}} 442 // {{{ commit() 443 444 /** 445 * Commit the current transaction. 446 */ 447 function commit() 448 { 449 if ($this->transaction_opcount > 0) { 450 if ($this->_db) { 451 if (!@mysqli_select_db($this->connection, $this->_db)) { 452 return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); 453 } 454 } 455 $result = @mysqli_query($this->connection, 'COMMIT'); 456 $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1'); 457 $this->transaction_opcount = 0; 458 if (!$result) { 459 return $this->mysqlRaiseError(); 460 } 461 } 462 return DB_OK; 463 } 464 465 // }}} 466 // {{{ rollback() 467 468 /** 469 * Roll back (undo) the current transaction. 470 */ 471 function rollback() 472 { 473 if ($this->transaction_opcount > 0) { 474 if ($this->_db) { 475 if (!@mysqli_select_db($this->connection, $this->_db)) { 476 return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); 477 } 478 } 479 $result = @mysqli_query($this->connection, 'ROLLBACK'); 480 $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1'); 481 $this->transaction_opcount = 0; 482 if (!$result) { 483 return $this->mysqlRaiseError(); 484 } 485 } 486 return DB_OK; 487 } 488 489 // }}} 490 // {{{ affectedRows() 491 492 /** 493 * Gets the number of rows affected by the data manipulation 494 * query. For other queries, this function returns 0. 495 * 496 * @return integer number of rows affected by the last query 497 */ 498 function affectedRows() 499 { 500 if (DB::isManip($this->last_query)) { 501 return @mysqli_affected_rows($this->connection); 502 } else { 503 return 0; 504 } 505 } 506 507 // }}} 508 // {{{ errorNative() 509 510 /** 511 * Get the native error code of the last error (if any) that 512 * occured on the current connection. 513 * 514 * @return int native MySQL error code 515 * @access public 516 */ 517 function errorNative() 518 { 519 return @mysqli_errno($this->connection); 520 } 521 522 // }}} 523 // {{{ nextId() 524 525 /** 526 * Returns the next free id in a sequence 527 * 528 * @param string $seq_name name of the sequence 529 * @param boolean $ondemand when true, the seqence is automatically 530 * created if it does not exist 531 * 532 * @return int the next id number in the sequence. DB_Error if problem. 533 * 534 * @internal 535 * @see DB_common::nextID() 536 * @access public 537 */ 538 function nextId($seq_name, $ondemand = true) 539 { 540 $seqname = $this->getSequenceName($seq_name); 541 do { 542 $repeat = 0; 543 $this->pushErrorHandling(PEAR_ERROR_RETURN); 544 $result = $this->query("UPDATE $seqname} ". 545 'SET id=LAST_INSERT_ID(id+1)'); 546 $this->popErrorHandling(); 547 if ($result === DB_OK) { 548 /** COMMON CASE **/ 549 $id = @mysqli_insert_id($this->connection); 550 if ($id != 0) { 551 return $id; 552 } 553 /** EMPTY SEQ TABLE **/ 554 // Sequence table must be empty for some reason, so fill it and return 1 555 // Obtain a user-level lock 556 $result = $this->getOne("SELECT GET_LOCK('$seqname}_lock',10)"); 557 if (DB::isError($result)) { 558 return $this->raiseError($result); 559 } 560 if ($result == 0) { 561 // Failed to get the lock, bail with a DB_ERROR_NOT_LOCKED error 562 return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); 563 } 564 565 // add the default value 566 $result = $this->query("REPLACE INTO $seqname} (id) VALUES (0)"); 567 if (DB::isError($result)) { 568 return $this->raiseError($result); 569 } 570 571 // Release the lock 572 $result = $this->getOne("SELECT RELEASE_LOCK('$seqname}_lock')"); 573 if (DB::isError($result)) { 574 return $this->raiseError($result); 575 } 576 // We know what the result will be, so no need to try again 577 return 1; 578 579 /** ONDEMAND TABLE CREATION **/ 580 } elseif ($ondemand && DB::isError($result) && 581 $result->getCode() == DB_ERROR_NOSUCHTABLE) 582 { 583 $result = $this->createSequence($seq_name); 584 // Since createSequence initializes the ID to be 1, 585 // we do not need to retrieve the ID again (or we will get 2) 586 if (DB::isError($result)) { 587 return $this->raiseError($result); 588 } else { 589 // First ID of a newly created sequence is 1 590 return 1; 591 } 592 593 /** BACKWARDS COMPAT **/ 594 } elseif (DB::isError($result) && 595 $result->getCode() == DB_ERROR_ALREADY_EXISTS) 596 { 597 // see _BCsequence() comment 598 $result = $this->_BCsequence($seqname); 599 if (DB::isError($result)) { 600 return $this->raiseError($result); 601 } 602 $repeat = 1; 603 } 604 } while ($repeat); 605 606 return $this->raiseError($result); 607 } 608 609 /** 610 * Creates a new sequence 611 * 612 * @param string $seq_name name of the new sequence 613 * 614 * @return int DB_OK on success. A DB_Error object is returned if 615 * problems arise. 616 * 617 * @internal 618 * @see DB_common::createSequence() 619 * @access public 620 */ 621 function createSequence($seq_name) 622 { 623 $seqname = $this->getSequenceName($seq_name); 624 $res = $this->query("CREATE TABLE $seqname} ". 625 '(id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'. 626 ' PRIMARY KEY(id))'); 627 if (DB::isError($res)) { 628 return $res; 629 } 630 // insert yields value 1, nextId call will generate ID 2 631 return $this->query("INSERT INTO $seqname} (id) VALUES (0)"); 632 } 633 634 // }}} 635 // {{{ dropSequence() 636 637 /** 638 * Deletes a sequence 639 * 640 * @param string $seq_name name of the sequence to be deleted 641 * 642 * @return int DB_OK on success. DB_Error if problems. 643 * 644 * @internal 645 * @see DB_common::dropSequence() 646 * @access public 647 */ 648 function dropSequence($seq_name) 649 { 650 return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); 651 } 652 653 // }}} 654 // {{{ _BCsequence() 655 656 /** 657 * Backwards compatibility with old sequence emulation implementation 658 * (clean up the dupes). 659 * 660 * @param string $seqname The sequence name to clean up 661 * @return mixed DB_Error or true 662 */ 663 function _BCsequence($seqname) 664 { 665 // Obtain a user-level lock... this will release any previous 666 // application locks, but unlike LOCK TABLES, it does not abort 667 // the current transaction and is much less frequently used. 668 $result = $this->getOne("SELECT GET_LOCK('$seqname}_lock',10)"); 669 if (DB::isError($result)) { 670 return $result; 671 } 672 if ($result == 0) { 673 // Failed to get the lock, can't do the conversion, bail 674 // with a DB_ERROR_NOT_LOCKED error 675 return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); 676 } 677 678 $highest_id = $this->getOne("SELECT MAX(id) FROM $seqname}"); 679 if (DB::isError($highest_id)) { 680 return $highest_id; 681 } 682 // This should kill all rows except the highest 683 // We should probably do something if $highest_id isn't 684 // numeric, but I'm at a loss as how to handle that... 685 $result = $this->query("DELETE FROM $seqname} WHERE id <> $highest_id"); 686 if (DB::isError($result)) { 687 return $result; 688 } 689 690 // If another thread has been waiting for this lock, 691 // it will go thru the above procedure, but will have no 692 // real effect 693 $result = $this->getOne("SELECT RELEASE_LOCK('$seqname}_lock')"); 694 if (DB::isError($result)) { 695 return $result; 696 } 697 return true; 698 } 699 700 // }}} 701 // {{{ quoteIdentifier() 702 703 /** 704 * Quote a string so it can be safely used as a table or column name 705 * 706 * Quoting style depends on which database driver is being used. 707 * 708 * MySQL can't handle the backtick character (<kbd>`</kbd>) in 709 * table or column names. 710 * 711 * @param string $str identifier name to be quoted 712 * 713 * @return string quoted identifier string 714 * 715 * @since 1.6.0 716 * @access public 717 * @internal 718 */ 719 function quoteIdentifier($str) 720 { 721 return '`' . $str . '`'; 722 } 723 724 // }}} 725 // {{{ escapeSimple() 726 727 /** 728 * Escape a string according to the current DBMS's standards 729 * 730 * @param string $str the string to be escaped 731 * 732 * @return string the escaped string 733 * 734 * @internal 735 */ 736 function escapeSimple($str) { 737 return @mysqli_real_escape_string($this->connection, $str); 738 } 739 740 // }}} 741 // {{{ modifyQuery() 742 743 function modifyQuery($query) 744 { 745 return $query; 746 } 747 748 // }}} 749 // {{{ modifyLimitQuery() 750 751 function modifyLimitQuery($query, $from, $count, $params = array()) 752 { 753 if (DB::isManip($query)) { 754 return $query . " LIMIT $count"; 755 } else { 756 return $query . " LIMIT $from, $count"; 757 } 758 } 759 760 // }}} 761 // {{{ mysqlRaiseError() 762 763 /** 764 * Gather information about an error, then use that info to create a 765 * DB error object and finally return that object. 766 * 767 * @param integer $errno PEAR error number (usually a DB constant) if 768 * manually raising an error 769 * @return object DB error object 770 * @see DB_common::errorCode() 771 * @see DB_common::raiseError() 772 */ 773 function mysqlRaiseError($errno = null) 774 { 775 if ($errno === null) { 776 if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { 777 $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT; 778 $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL; 779 $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT; 780 } else { 781 // Doing this in case mode changes during runtime. 782 $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS; 783 $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT; 784 $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS; 785 } 786 $errno = $this->errorCode(mysqli_errno($this->connection)); 787 } 788 return $this->raiseError($errno, null, null, null, 789 @mysqli_errno($this->connection) . ' ** ' . 790 @mysqli_error($this->connection)); 791 } 792 793 // }}} 794 // {{{ tableInfo() 795 796 /** 797 * Returns information about a table or a result set. 798 * 799 * WARNING: this method will probably not work because the mysqli_*() 800 * functions it relies upon may not exist. 801 * 802 * @param object|string $result DB_result object from a query or a 803 * string containing the name of a table 804 * @param int $mode a valid tableInfo mode 805 * @return array an associative array with the information requested 806 * or an error object if something is wrong 807 * @access public 808 * @internal 809 * @see DB_common::tableInfo() 810 */ 811 function tableInfo($result, $mode = null) { 812 if (isset($result->result)) { 813 /* 814 * Probably received a result object. 815 * Extract the result resource identifier. 816 */ 817 $id = $result->result; 818 $got_string = false; 819 } elseif (is_string($result)) { 820 /* 821 * Probably received a table name. 822 * Create a result resource identifier. 823 */ 824 $id = @mysqli_query($this->connection, 825 "SELECT * FROM $result LIMIT 0"); 826 $got_string = true; 827 } else { 828 /* 829 * Probably received a result resource identifier. 830 * Copy it. 831 * Deprecated. Here for compatibility only. 832 */ 833 $id = $result; 834 $got_string = false; 835 } 836 837 if (!is_a($id, 'mysqli_result')) { 838 return $this->mysqlRaiseError(DB_ERROR_NEED_MORE_DATA); 839 } 840 841 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 842 $case_func = 'strtolower'; 843 } else { 844 $case_func = 'strval'; 845 } 846 847 $count = @mysqli_num_fields($id); 848 849 // made this IF due to performance (one if is faster than $count if's) 850 if (!$mode) { 851 for ($i=0; $i<$count; $i++) { 852 $tmp = @mysqli_fetch_field($id); 853 $res[$i]['table'] = $case_func($tmp->table); 854 $res[$i]['name'] = $case_func($tmp->name); 855 $res[$i]['type'] = isset($this->mysqli_types[$tmp->type]) ? 856 $this->mysqli_types[$tmp->type] : 857 'unknown'; 858 $res[$i]['len'] = $tmp->max_length; 859 860 $res[$i]['flags'] = ''; 861 foreach ($this->mysqli_flags as $const => $means) { 862 if ($tmp->flags & $const) { 863 $res[$i]['flags'] .= $means . ' '; 864 } 865 } 866 if ($tmp->def) { 867 $res[$i]['flags'] .= 'default_' . rawurlencode($tmp->def); 868 } 869 $res[$i]['flags'] = trim($res[$i]['flags']); 870 } 871 } else { // full 872 $res['num_fields']= $count; 873 874 for ($i=0; $i<$count; $i++) { 875 $tmp = @mysqli_fetch_field($id); 876 $res[$i]['table'] = $case_func($tmp->table); 877 $res[$i]['name'] = $case_func($tmp->name); 878 $res[$i]['type'] = isset($this->mysqli_types[$tmp->type]) ? 879 $this->mysqli_types[$tmp->type] : 880 'unknown'; 881 $res[$i]['len'] = $tmp->max_length; 882 883 $res[$i]['flags'] = ''; 884 foreach ($this->mysqli_flags as $const => $means) { 885 if ($tmp->flags & $const) { 886 $res[$i]['flags'] .= $means . ' '; 887 } 888 } 889 if ($tmp->def) { 890 $res[$i]['flags'] .= 'default_' . rawurlencode($tmp->def); 891 } 892 $res[$i]['flags'] = trim($res[$i]['flags']); 893 894 if ($mode & DB_TABLEINFO_ORDER) { 895 $res['order'][$res[$i]['name']] = $i; 896 } 897 if ($mode & DB_TABLEINFO_ORDERTABLE) { 898 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 899 } 900 } 901 } 902 903 // free the result only if we were called on a table 904 if ($got_string) { 905 @mysqli_free_result($id); 906 } 907 return $res; 908 } 909 910 // }}} 911 // {{{ getSpecialQuery() 912 913 /** 914 * Returns the query needed to get some backend info. 915 * 916 * @param string $type What kind of info you want to retrieve 917 * @return string The SQL query string 918 */ 919 function getSpecialQuery($type) 920 { 921 switch ($type) { 922 case 'tables': 923 return 'SHOW TABLES'; 924 case 'views': 925 return DB_ERROR_NOT_CAPABLE; 926 case 'users': 927 $sql = 'select distinct User from user'; 928 if ($this->dsn['database'] != 'mysql') { 929 $dsn = $this->dsn; 930 $dsn['database'] = 'mysql'; 931 if (DB::isError($db = DB::connect($dsn))) { 932 return $db; 933 } 934 $sql = $db->getCol($sql); 935 $db->disconnect(); 936 // XXX Fixme the mysql driver should take care of this 937 if (!@mysqli_select_db($this->connection, $this->dsn['database'])) { 938 return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); 939 } 940 } 941 return $sql; 942 case 'databases': 943 return 'SHOW DATABASES'; 944 default: 945 return null; 946 } 947 } 948 949 // }}} 950 951 } 952 953 /* 954 * Local variables: 955 * tab-width: 4 956 * c-basic-offset: 4 957 * End: 958 */ 959 960 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sat Feb 24 14:40:03 2007 | par Balluche grâce à PHPXref 0.7 |