| [ Index ] |
PHP Cross Reference of Joomla 2.5.4 DE |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * @package Joomla.Platform 4 * @subpackage Database 5 * 6 * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved. 7 * @license GNU General Public License version 2 or later; see LICENSE 8 */ 9 10 defined('JPATH_PLATFORM') or die; 11 12 JLoader::register('JDatabaseQueryMySQL', dirname(__FILE__) . '/mysqlquery.php'); 13 JLoader::register('JDatabaseExporterMySQL', dirname(__FILE__) . '/mysqlexporter.php'); 14 JLoader::register('JDatabaseImporterMySQL', dirname(__FILE__) . '/mysqlimporter.php'); 15 16 /** 17 * MySQL database driver 18 * 19 * @package Joomla.Platform 20 * @subpackage Database 21 * @see http://dev.mysql.com/doc/ 22 * @since 11.1 23 */ 24 class JDatabaseMySQL extends JDatabase 25 { 26 /** 27 * The name of the database driver. 28 * 29 * @var string 30 * @since 11.1 31 */ 32 public $name = 'mysql'; 33 34 /** 35 * The character(s) used to quote SQL statement names such as table names or field names, 36 * etc. The child classes should define this as necessary. If a single character string the 37 * same character is used for both sides of the quoted name, else the first character will be 38 * used for the opening quote and the second for the closing quote. 39 * 40 * @var string 41 * @since 11.1 42 */ 43 protected $nameQuote = '`'; 44 45 /** 46 * The null or zero representation of a timestamp for the database driver. This should be 47 * defined in child classes to hold the appropriate value for the engine. 48 * 49 * @var string 50 * @since 11.1 51 */ 52 protected $nullDate = '0000-00-00 00:00:00'; 53 54 /** 55 * Constructor. 56 * 57 * @param array $options Array of database options with keys: host, user, password, database, select. 58 * 59 * @since 11.1 60 */ 61 protected function __construct($options) 62 { 63 // Get some basic values from the options. 64 $options['host'] = (isset($options['host'])) ? $options['host'] : 'localhost'; 65 $options['user'] = (isset($options['user'])) ? $options['user'] : 'root'; 66 $options['password'] = (isset($options['password'])) ? $options['password'] : ''; 67 $options['database'] = (isset($options['database'])) ? $options['database'] : ''; 68 $options['select'] = (isset($options['select'])) ? (bool) $options['select'] : true; 69 70 // Make sure the MySQL extension for PHP is installed and enabled. 71 if (!function_exists('mysql_connect')) 72 { 73 74 // Legacy error handling switch based on the JError::$legacy switch. 75 // @deprecated 12.1 76 if (JError::$legacy) 77 { 78 $this->errorNum = 1; 79 $this->errorMsg = JText::_('JLIB_DATABASE_ERROR_ADAPTER_MYSQL'); 80 return; 81 } 82 else 83 { 84 throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_ADAPTER_MYSQL')); 85 } 86 } 87 88 // Attempt to connect to the server. 89 if (!($this->connection = @ mysql_connect($options['host'], $options['user'], $options['password'], true))) 90 { 91 92 // Legacy error handling switch based on the JError::$legacy switch. 93 // @deprecated 12.1 94 if (JError::$legacy) 95 { 96 $this->errorNum = 2; 97 $this->errorMsg = JText::_('JLIB_DATABASE_ERROR_CONNECT_MYSQL'); 98 return; 99 } 100 else 101 { 102 throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_CONNECT_MYSQL')); 103 } 104 } 105 106 // Finalize initialisation 107 parent::__construct($options); 108 109 // Set sql_mode to non_strict mode 110 mysql_query("SET @@SESSION.sql_mode = '';", $this->connection); 111 112 // If auto-select is enabled select the given database. 113 if ($options['select'] && !empty($options['database'])) 114 { 115 $this->select($options['database']); 116 } 117 } 118 119 /** 120 * Destructor. 121 * 122 * @since 11.1 123 */ 124 public function __destruct() 125 { 126 if (is_resource($this->connection)) 127 { 128 mysql_close($this->connection); 129 } 130 } 131 132 /** 133 * Method to escape a string for usage in an SQL statement. 134 * 135 * @param string $text The string to be escaped. 136 * @param boolean $extra Optional parameter to provide extra escaping. 137 * 138 * @return string The escaped string. 139 * 140 * @since 11.1 141 */ 142 public function escape($text, $extra = false) 143 { 144 $result = mysql_real_escape_string($text, $this->getConnection()); 145 146 if ($extra) 147 { 148 $result = addcslashes($result, '%_'); 149 } 150 151 return $result; 152 } 153 154 /** 155 * Test to see if the MySQL connector is available. 156 * 157 * @return boolean True on success, false otherwise. 158 * 159 * @since 11.1 160 */ 161 public static function test() 162 { 163 return (function_exists('mysql_connect')); 164 } 165 166 /** 167 * Determines if the connection to the server is active. 168 * 169 * @return boolean True if connected to the database engine. 170 * 171 * @since 11.1 172 */ 173 public function connected() 174 { 175 if (is_resource($this->connection)) 176 { 177 return mysql_ping($this->connection); 178 } 179 180 return false; 181 } 182 183 /** 184 * Drops a table from the database. 185 * 186 * @param string $tableName The name of the database table to drop. 187 * @param boolean $ifExists Optionally specify that the table must exist before it is dropped. 188 * 189 * @return JDatabaseMySQL Returns this object to support chaining. 190 * 191 * @since 11.1 192 * @throws JDatabaseException 193 */ 194 public function dropTable($tableName, $ifExists = true) 195 { 196 $query = $this->getQuery(true); 197 198 $this->setQuery('DROP TABLE ' . ($ifExists ? 'IF EXISTS ' : '') . $query->quoteName($tableName)); 199 200 $this->query(); 201 202 return $this; 203 } 204 205 /** 206 * Get the number of affected rows for the previous executed SQL statement. 207 * 208 * @return integer The number of affected rows. 209 * 210 * @since 11.1 211 */ 212 public function getAffectedRows() 213 { 214 return mysql_affected_rows($this->connection); 215 } 216 217 /** 218 * Method to get the database collation in use by sampling a text field of a table in the database. 219 * 220 * @return mixed The collation in use by the database (string) or boolean false if not supported. 221 * 222 * @since 11.1 223 * @throws JDatabaseException 224 */ 225 public function getCollation() 226 { 227 $this->setQuery('SHOW FULL COLUMNS FROM #__users'); 228 $array = $this->loadAssocList(); 229 return $array['2']['Collation']; 230 } 231 232 /** 233 * Gets an exporter class object. 234 * 235 * @return JDatabaseExporterMySQL An exporter object. 236 * 237 * @since 11.1 238 * @throws JDatabaseException 239 */ 240 public function getExporter() 241 { 242 // Make sure we have an exporter class for this driver. 243 if (!class_exists('JDatabaseExporterMySQL')) 244 { 245 throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_MISSING_EXPORTER')); 246 } 247 248 $o = new JDatabaseExporterMySQL; 249 $o->setDbo($this); 250 251 return $o; 252 } 253 254 /** 255 * Gets an importer class object. 256 * 257 * @return JDatabaseImporterMySQL An importer object. 258 * 259 * @since 11.1 260 * @throws JDatabaseException 261 */ 262 public function getImporter() 263 { 264 // Make sure we have an importer class for this driver. 265 if (!class_exists('JDatabaseImporterMySQL')) 266 { 267 throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_MISSING_IMPORTER')); 268 } 269 270 $o = new JDatabaseImporterMySQL; 271 $o->setDbo($this); 272 273 return $o; 274 } 275 276 /** 277 * Get the number of returned rows for the previous executed SQL statement. 278 * 279 * @param resource $cursor An optional database cursor resource to extract the row count from. 280 * 281 * @return integer The number of returned rows. 282 * 283 * @since 11.1 284 */ 285 public function getNumRows($cursor = null) 286 { 287 return mysql_num_rows($cursor ? $cursor : $this->cursor); 288 } 289 290 /** 291 * Get the current or query, or new JDatabaseQuery object. 292 * 293 * @param boolean $new False to return the last query set, True to return a new JDatabaseQuery object. 294 * 295 * @return mixed The current value of the internal SQL variable or a new JDatabaseQuery object. 296 * 297 * @since 11.1 298 * @throws JDatabaseException 299 */ 300 public function getQuery($new = false) 301 { 302 if ($new) 303 { 304 // Make sure we have a query class for this driver. 305 if (!class_exists('JDatabaseQueryMySQL')) 306 { 307 throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_MISSING_QUERY')); 308 } 309 return new JDatabaseQueryMySQL($this); 310 } 311 else 312 { 313 return $this->sql; 314 } 315 } 316 317 /** 318 * Shows the table CREATE statement that creates the given tables. 319 * 320 * @param mixed $tables A table name or a list of table names. 321 * 322 * @return array A list of the create SQL for the tables. 323 * 324 * @since 11.1 325 * @throws JDatabaseException 326 */ 327 public function getTableCreate($tables) 328 { 329 // Initialise variables. 330 $result = array(); 331 332 // Sanitize input to an array and iterate over the list. 333 settype($tables, 'array'); 334 foreach ($tables as $table) 335 { 336 // Set the query to get the table CREATE statement. 337 $this->setQuery('SHOW CREATE table ' . $this->quoteName($this->escape($table))); 338 $row = $this->loadRow(); 339 340 // Populate the result array based on the create statements. 341 $result[$table] = $row[1]; 342 } 343 344 return $result; 345 } 346 347 /** 348 * Retrieves field information about a given table. 349 * 350 * @param string $table The name of the database table. 351 * @param boolean $typeOnly True to only return field types. 352 * 353 * @return array An array of fields for the database table. 354 * 355 * @since 11.1 356 * @throws JDatabaseException 357 */ 358 public function getTableColumns($table, $typeOnly = true) 359 { 360 $result = array(); 361 362 // Set the query to get the table fields statement. 363 $this->setQuery('SHOW FULL COLUMNS FROM ' . $this->quoteName($this->escape($table))); 364 $fields = $this->loadObjectList(); 365 366 // If we only want the type as the value add just that to the list. 367 if ($typeOnly) 368 { 369 foreach ($fields as $field) 370 { 371 $result[$field->Field] = preg_replace("/[(0-9)]/", '', $field->Type); 372 } 373 } 374 // If we want the whole field data object add that to the list. 375 else 376 { 377 foreach ($fields as $field) 378 { 379 $result[$field->Field] = $field; 380 } 381 } 382 383 return $result; 384 } 385 386 /** 387 * Get the details list of keys for a table. 388 * 389 * @param string $table The name of the table. 390 * 391 * @return array An array of the column specification for the table. 392 * 393 * @since 11.1 394 * @throws JDatabaseException 395 */ 396 public function getTableKeys($table) 397 { 398 // Get the details columns information. 399 $this->setQuery('SHOW KEYS FROM ' . $this->quoteName($table)); 400 $keys = $this->loadObjectList(); 401 402 return $keys; 403 } 404 405 /** 406 * Method to get an array of all tables in the database. 407 * 408 * @return array An array of all the tables in the database. 409 * 410 * @since 11.1 411 * @throws JDatabaseException 412 */ 413 public function getTableList() 414 { 415 // Set the query to get the tables statement. 416 $this->setQuery('SHOW TABLES'); 417 $tables = $this->loadColumn(); 418 419 return $tables; 420 } 421 422 /** 423 * Get the version of the database connector. 424 * 425 * @return string The database connector version. 426 * 427 * @since 11.1 428 */ 429 public function getVersion() 430 { 431 return mysql_get_server_info($this->connection); 432 } 433 434 /** 435 * Determines if the database engine supports UTF-8 character encoding. 436 * 437 * @return boolean True if supported. 438 * 439 * @since 11.1 440 * @deprecated 12.1 441 */ 442 public function hasUTF() 443 { 444 JLog::add('JDatabaseMySQL::hasUTF() is deprecated.', JLog::WARNING, 'deprecated'); 445 return true; 446 } 447 448 /** 449 * Method to get the auto-incremented value from the last INSERT statement. 450 * 451 * @return integer The value of the auto-increment field from the last inserted row. 452 * 453 * @since 11.1 454 */ 455 public function insertid() 456 { 457 return mysql_insert_id($this->connection); 458 } 459 460 /** 461 * Locks a table in the database. 462 * 463 * @param string $table The name of the table to unlock. 464 * 465 * @return JDatabaseMySQL Returns this object to support chaining. 466 * 467 * @since 11.4 468 * @throws JDatabaseException 469 */ 470 public function lockTable($table) 471 { 472 $this->setQuery('LOCK TABLES ' . $this->quoteName($table) . ' WRITE')->query(); 473 474 return $this; 475 } 476 477 /** 478 * Execute the SQL statement. 479 * 480 * @return mixed A database cursor resource on success, boolean false on failure. 481 * 482 * @since 11.1 483 * @throws JDatabaseException 484 */ 485 public function query() 486 { 487 if (!is_resource($this->connection)) 488 { 489 // Legacy error handling switch based on the JError::$legacy switch. 490 // @deprecated 12.1 491 if (JError::$legacy) 492 { 493 if ($this->debug) 494 { 495 JError::raiseError(500, 'JDatabaseMySQL::query: ' . $this->errorNum . ' - ' . $this->errorMsg); 496 } 497 return false; 498 } 499 else 500 { 501 JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'database'); 502 throw new JDatabaseException($this->errorMsg, $this->errorNum); 503 } 504 } 505 506 // Take a local copy so that we don't modify the original query and cause issues later 507 $sql = $this->replacePrefix((string) $this->sql); 508 if ($this->limit > 0 || $this->offset > 0) 509 { 510 $sql .= ' LIMIT ' . $this->offset . ', ' . $this->limit; 511 } 512 513 // If debugging is enabled then let's log the query. 514 if ($this->debug) 515 { 516 // Increment the query counter and add the query to the object queue. 517 $this->count++; 518 $this->log[] = $sql; 519 520 JLog::add($sql, JLog::DEBUG, 'databasequery'); 521 } 522 523 // Reset the error values. 524 $this->errorNum = 0; 525 $this->errorMsg = ''; 526 527 // Execute the query. 528 $this->cursor = mysql_query($sql, $this->connection); 529 530 // If an error occurred handle it. 531 if (!$this->cursor) 532 { 533 $this->errorNum = (int) mysql_errno($this->connection); 534 $this->errorMsg = (string) mysql_error($this->connection) . ' SQL=' . $sql; 535 536 // Legacy error handling switch based on the JError::$legacy switch. 537 // @deprecated 12.1 538 if (JError::$legacy) 539 { 540 if ($this->debug) 541 { 542 JError::raiseError(500, 'JDatabaseMySQL::query: ' . $this->errorNum . ' - ' . $this->errorMsg); 543 } 544 return false; 545 } 546 else 547 { 548 JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'databasequery'); 549 throw new JDatabaseException($this->errorMsg, $this->errorNum); 550 } 551 } 552 553 return $this->cursor; 554 } 555 556 /** 557 * Renames a table in the database. 558 * 559 * @param string $oldTable The name of the table to be renamed 560 * @param string $newTable The new name for the table. 561 * @param string $backup Not used by MySQL. 562 * @param string $prefix Not used by MySQL. 563 * 564 * @return JDatabase Returns this object to support chaining. 565 * 566 * @since 11.4 567 * @throws JDatabaseException 568 */ 569 public function renameTable($oldTable, $newTable, $backup = null, $prefix = null) 570 { 571 $this->setQuery('RENAME TABLE ' . $oldTable . ' TO ' . $newTable)->query(); 572 573 return $this; 574 } 575 576 /** 577 * Select a database for use. 578 * 579 * @param string $database The name of the database to select for use. 580 * 581 * @return boolean True if the database was successfully selected. 582 * 583 * @since 11.1 584 * @throws JDatabaseException 585 */ 586 public function select($database) 587 { 588 if (!$database) 589 { 590 return false; 591 } 592 593 if (!mysql_select_db($database, $this->connection)) 594 { 595 // Legacy error handling switch based on the JError::$legacy switch. 596 // @deprecated 12.1 597 if (JError::$legacy) 598 { 599 $this->errorNum = 3; 600 $this->errorMsg = JText::_('JLIB_DATABASE_ERROR_DATABASE_CONNECT'); 601 return false; 602 } 603 else 604 { 605 throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_DATABASE_CONNECT')); 606 } 607 } 608 609 return true; 610 } 611 612 /** 613 * Set the connection to use UTF-8 character encoding. 614 * 615 * @return boolean True on success. 616 * 617 * @since 11.1 618 */ 619 public function setUTF() 620 { 621 return mysql_query("SET NAMES 'utf8'", $this->connection); 622 } 623 624 /** 625 * Method to commit a transaction. 626 * 627 * @return void 628 * 629 * @since 11.1 630 * @throws JDatabaseException 631 */ 632 public function transactionCommit() 633 { 634 $this->setQuery('COMMIT'); 635 $this->query(); 636 } 637 638 /** 639 * Method to roll back a transaction. 640 * 641 * @return void 642 * 643 * @since 11.1 644 * @throws JDatabaseException 645 */ 646 public function transactionRollback() 647 { 648 $this->setQuery('ROLLBACK'); 649 $this->query(); 650 } 651 652 /** 653 * Method to initialize a transaction. 654 * 655 * @return void 656 * 657 * @since 11.1 658 * @throws JDatabaseException 659 */ 660 public function transactionStart() 661 { 662 $this->setQuery('START TRANSACTION'); 663 $this->query(); 664 } 665 666 /** 667 * Method to fetch a row from the result set cursor as an array. 668 * 669 * @param mixed $cursor The optional result set cursor from which to fetch the row. 670 * 671 * @return mixed Either the next row from the result set or false if there are no more rows. 672 * 673 * @since 11.1 674 */ 675 protected function fetchArray($cursor = null) 676 { 677 return mysql_fetch_row($cursor ? $cursor : $this->cursor); 678 } 679 680 /** 681 * Method to fetch a row from the result set cursor as an associative array. 682 * 683 * @param mixed $cursor The optional result set cursor from which to fetch the row. 684 * 685 * @return mixed Either the next row from the result set or false if there are no more rows. 686 * 687 * @since 11.1 688 */ 689 protected function fetchAssoc($cursor = null) 690 { 691 return mysql_fetch_assoc($cursor ? $cursor : $this->cursor); 692 } 693 694 /** 695 * Method to fetch a row from the result set cursor as an object. 696 * 697 * @param mixed $cursor The optional result set cursor from which to fetch the row. 698 * @param string $class The class name to use for the returned row object. 699 * 700 * @return mixed Either the next row from the result set or false if there are no more rows. 701 * 702 * @since 11.1 703 */ 704 protected function fetchObject($cursor = null, $class = 'stdClass') 705 { 706 return mysql_fetch_object($cursor ? $cursor : $this->cursor, $class); 707 } 708 709 /** 710 * Method to free up the memory used for the result set. 711 * 712 * @param mixed $cursor The optional result set cursor from which to fetch the row. 713 * 714 * @return void 715 * 716 * @since 11.1 717 */ 718 protected function freeResult($cursor = null) 719 { 720 mysql_free_result($cursor ? $cursor : $this->cursor); 721 } 722 723 /** 724 * Diagnostic method to return explain information for a query. 725 * 726 * @return string The explain output. 727 * 728 * @since 11.1 729 * @deprecated 12.1 730 */ 731 public function explain() 732 { 733 // Deprecation warning. 734 JLog::add('JDatabaseMySQL::explain() is deprecated.', JLog::WARNING, 'deprecated'); 735 736 // Backup the current query so we can reset it later. 737 $backup = $this->sql; 738 739 // Prepend the current query with EXPLAIN so we get the diagnostic data. 740 $this->sql = 'EXPLAIN ' . $this->sql; 741 742 // Execute the query and get the result set cursor. 743 if (!($cursor = $this->query())) 744 { 745 return null; 746 } 747 748 // Build the HTML table. 749 $first = true; 750 $buffer = '<table id="explain-sql">'; 751 $buffer .= '<thead><tr><td colspan="99">' . $this->getQuery() . '</td></tr>'; 752 while ($row = $this->fetchAssoc($cursor)) 753 { 754 if ($first) 755 { 756 $buffer .= '<tr>'; 757 foreach ($row as $k => $v) 758 { 759 $buffer .= '<th>' . $k . '</th>'; 760 } 761 $buffer .= '</tr></thead><tbody>'; 762 $first = false; 763 } 764 $buffer .= '<tr>'; 765 foreach ($row as $k => $v) 766 { 767 $buffer .= '<td>' . $v . '</td>'; 768 } 769 $buffer .= '</tr>'; 770 } 771 $buffer .= '</tbody></table>'; 772 773 // Restore the original query to its state before we ran the explain. 774 $this->sql = $backup; 775 776 // Free up system resources and return. 777 $this->freeResult($cursor); 778 779 return $buffer; 780 } 781 782 /** 783 * Execute a query batch. 784 * 785 * @param boolean $abortOnError Abort on error. 786 * @param boolean $transactionSafe Transaction safe queries. 787 * 788 * @return mixed A database resource if successful, false if not. 789 * 790 * @deprecated 12.1 791 * @since 11.1 792 */ 793 public function queryBatch($abortOnError = true, $transactionSafe = false) 794 { 795 // Deprecation warning. 796 JLog::add('JDatabaseMySQL::queryBatch() is deprecated.', JLog::WARNING, 'deprecated'); 797 798 $sql = $this->replacePrefix((string) $this->sql); 799 $this->errorNum = 0; 800 $this->errorMsg = ''; 801 802 // If the batch is meant to be transaction safe then we need to wrap it in a transaction. 803 if ($transactionSafe) 804 { 805 $sql = 'START TRANSACTION;' . rtrim($sql, "; \t\r\n\0") . '; COMMIT;'; 806 } 807 $queries = $this->splitSql($sql); 808 $error = 0; 809 foreach ($queries as $query) 810 { 811 $query = trim($query); 812 if ($query != '') 813 { 814 $this->cursor = mysql_query($query, $this->connection); 815 if ($this->debug) 816 { 817 $this->count++; 818 $this->log[] = $query; 819 } 820 if (!$this->cursor) 821 { 822 $error = 1; 823 $this->errorNum .= mysql_errno($this->connection) . ' '; 824 $this->errorMsg .= mysql_error($this->connection) . " SQL=$query <br />"; 825 if ($abortOnError) 826 { 827 return $this->cursor; 828 } 829 } 830 } 831 } 832 return $error ? false : true; 833 } 834 835 /** 836 * Unlocks tables in the database. 837 * 838 * @return JDatabaseMySQL Returns this object to support chaining. 839 * 840 * @since 11.4 841 * @throws JDatabaseException 842 */ 843 public function unlockTables() 844 { 845 $this->setQuery('UNLOCK TABLES')->query(); 846 847 return $this; 848 } 849 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Tue Apr 3 11:40:28 2012 | Cross-referenced by PHPXref 0.7.1 |