[ Index ] |
PHP Cross Reference of MyBB 1.8.38 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * MyBB 1.8 4 * Copyright 2014 MyBB Group, All Rights Reserved 5 * 6 * Website: http://www.mybb.com 7 * License: http://www.mybb.com/about/license 8 * 9 */ 10 11 class DB_MySQL implements DB_Base 12 { 13 /** 14 * The title of this layer. 15 * 16 * @var string 17 */ 18 public $title = "MySQL"; 19 20 /** 21 * The short title of this layer. 22 * 23 * @var string 24 */ 25 public $short_title = "MySQL"; 26 27 /** 28 * The type of db software being used. 29 * 30 * @var string 31 */ 32 public $type; 33 34 /** 35 * A count of the number of queries. 36 * 37 * @var int 38 */ 39 public $query_count = 0; 40 41 /** 42 * A list of the performed queries. 43 * 44 * @var array 45 */ 46 public $querylist = array(); 47 48 /** 49 * 1 if error reporting enabled, 0 if disabled. 50 * 51 * @var boolean 52 */ 53 public $error_reporting = 1; 54 55 /** 56 * The read database connection resource. 57 * 58 * @var resource 59 */ 60 public $read_link; 61 62 /** 63 * The write database connection resource 64 * 65 * @var resource 66 */ 67 public $write_link; 68 69 /** 70 * Reference to the last database connection resource used. 71 * 72 * @var resource 73 */ 74 public $current_link; 75 76 /** 77 * @var array 78 */ 79 public $connections = array(); 80 81 /** 82 * The database name. 83 * 84 * @var string 85 */ 86 public $database; 87 88 /** 89 * Explanation of a query. 90 * 91 * @var string 92 */ 93 public $explain; 94 95 /** 96 * The current version of MySQL. 97 * 98 * @var string 99 */ 100 public $version; 101 102 /** 103 * The current table type in use (myisam/innodb) 104 * 105 * @var string 106 */ 107 public $table_type = "myisam"; 108 109 /** 110 * The table prefix used for simple select, update, insert and delete queries 111 * 112 * @var string 113 */ 114 public $table_prefix; 115 116 /** 117 * The extension used to run the SQL database 118 * 119 * @var string 120 */ 121 public $engine = "mysql"; 122 123 /** 124 * Weather or not this engine can use the search functionality 125 * 126 * @var boolean 127 */ 128 public $can_search = true; 129 130 /** 131 * The database encoding currently in use (if supported) 132 * 133 * @var string 134 */ 135 public $db_encoding = "utf8"; 136 137 /** 138 * The time spent performing queries 139 * 140 * @var float 141 */ 142 public $query_time = 0; 143 144 /** 145 * Stores previous run query type: 1 => write; 0 => read 146 * 147 * @var int 148 */ 149 150 protected $last_query_type = 0; 151 152 /** 153 * Connect to the database server. 154 * 155 * @param array $config Array of DBMS connection details. 156 * @return resource The DB connection resource. Returns false on fail or -1 on a db connect failure. 157 */ 158 function connect($config) 159 { 160 // Simple connection to one server 161 if(array_key_exists('hostname', $config)) 162 { 163 $connections['read'][] = $config; 164 } 165 // Connecting to more than one server 166 else 167 { 168 // Specified multiple servers, but no specific read/write servers 169 if(!array_key_exists('read', $config)) 170 { 171 foreach($config as $key => $settings) 172 { 173 if(is_int($key)) 174 { 175 $connections['read'][] = $settings; 176 } 177 } 178 } 179 // Specified both read & write servers 180 else 181 { 182 $connections = $config; 183 } 184 } 185 186 if(isset($config['encoding'])) 187 { 188 $this->db_encoding = $config['encoding']; 189 } 190 191 // Actually connect to the specified servers 192 foreach(array('read', 'write') as $type) 193 { 194 if(!isset($connections[$type]) || !is_array($connections[$type])) 195 { 196 break; 197 } 198 199 if(array_key_exists('hostname', $connections[$type])) 200 { 201 $details = $connections[$type]; 202 unset($connections[$type]); 203 $connections[$type][] = $details; 204 } 205 206 // Shuffle the connections 207 shuffle($connections[$type]); 208 209 // Loop-de-loop 210 foreach($connections[$type] as $single_connection) 211 { 212 $connect_function = "mysql_connect"; 213 if(isset($single_connection['pconnect'])) 214 { 215 $connect_function = "mysql_pconnect"; 216 } 217 218 $link = "{$type}_link"; 219 220 get_execution_time(); 221 222 $this->$link = @$connect_function($single_connection['hostname'], $single_connection['username'], $single_connection['password'], 1); 223 224 $time_spent = get_execution_time(); 225 $this->query_time += $time_spent; 226 227 // Successful connection? break down brother! 228 if($this->$link) 229 { 230 $this->connections[] = "[".strtoupper($type)."] {$single_connection['username']}@{$single_connection['hostname']} (Connected in ".format_time_duration($time_spent).")"; 231 break; 232 } 233 else 234 { 235 $this->connections[] = "<span style=\"color: red\">[FAILED] [".strtoupper($type)."] {$single_connection['username']}@{$single_connection['hostname']}</span>"; 236 } 237 } 238 } 239 240 // No write server was specified (simple connection or just multiple servers) - mirror write link 241 if(!array_key_exists('write', $connections)) 242 { 243 $this->write_link = &$this->read_link; 244 } 245 246 // Have no read connection? 247 if(!$this->read_link) 248 { 249 $this->error("[READ] Unable to connect to MySQL server"); 250 return false; 251 } 252 // No write? 253 else if(!$this->write_link) 254 { 255 $this->error("[WRITE] Unable to connect to MySQL server"); 256 return false; 257 } 258 259 // Select databases 260 if(!$this->select_db($config['database'])) 261 { 262 return -1; 263 } 264 265 $this->current_link = &$this->read_link; 266 return $this->read_link; 267 } 268 269 /** 270 * Selects the database to use. 271 * 272 * @param string $database The database name. 273 * @return boolean True when successfully connected, false if not. 274 */ 275 function select_db($database) 276 { 277 $this->database = $database; 278 279 $this->current_link = &$this->read_link; 280 $read_success = @mysql_select_db($database, $this->read_link) or $this->error("[READ] Unable to select database", $this->read_link); 281 if($this->write_link) 282 { 283 $this->current_link = &$this->write_link; 284 $write_success = @mysql_select_db($database, $this->write_link) or $this->error("[WRITE] Unable to select database", $this->write_link); 285 $success = ($read_success && $write_success ? true : false); 286 } 287 else 288 { 289 $success = $read_success; 290 } 291 292 if($success && $this->db_encoding) 293 { 294 // A little magic to support PHP 5.2.0, 5.2.1 and 5.2.2 295 if(version_compare(PHP_VERSION, '5.2.3', '>=')) { 296 @mysql_set_charset($this->db_encoding, $this->read_link); 297 } 298 else 299 { 300 $this->query("SET NAMES '{$this->db_encoding}'"); 301 } 302 303 if($write_success && count($this->connections) > 1) 304 { 305 if(version_compare(PHP_VERSION, '5.2.3', '>=')) { 306 @mysql_set_charset($this->db_encoding, $this->write_link); 307 } 308 else 309 { 310 $this->write_query("SET NAMES '{$this->db_encoding}'"); 311 } 312 } 313 } 314 return $success; 315 } 316 317 /** 318 * Query the database. 319 * 320 * @param string $string The query SQL. 321 * @param integer $hide_errors 1 if hide errors, 0 if not. 322 * @param integer $write_query 1 if executes on master database, 0 if not. 323 * @return resource The query data. 324 */ 325 function query($string, $hide_errors=0, $write_query=0) 326 { 327 global $mybb; 328 329 get_execution_time(); 330 331 // Only execute write queries on master database 332 if(($write_query || $this->last_query_type) && $this->write_link) 333 { 334 $this->current_link = &$this->write_link; 335 $query = @mysql_query($string, $this->write_link); 336 } 337 else 338 { 339 $this->current_link = &$this->read_link; 340 $query = @mysql_query($string, $this->read_link); 341 } 342 343 if($this->error_number() && !$hide_errors) 344 { 345 $this->error($string); 346 exit; 347 } 348 349 if($write_query) 350 { 351 $this->last_query_type = 1; 352 } 353 else 354 { 355 $this->last_query_type = 0; 356 } 357 358 $query_time = get_execution_time(); 359 $this->query_time += $query_time; 360 $this->query_count++; 361 362 if($mybb->debug_mode) 363 { 364 $this->explain_query($string, $query_time); 365 } 366 367 return $query; 368 } 369 370 /** 371 * Execute a write query on the master database 372 * 373 * @param string $query The query SQL. 374 * @param boolean|int $hide_errors 1 if hide errors, 0 if not. 375 * @return resource The query data. 376 */ 377 function write_query($query, $hide_errors=0) 378 { 379 return $this->query($query, $hide_errors, 1); 380 } 381 382 /** 383 * Explain a query on the database. 384 * 385 * @param string $string The query SQL. 386 * @param string $qtime The time it took to perform the query. 387 */ 388 function explain_query($string, $qtime) 389 { 390 global $plugins; 391 392 $debug_extra = ''; 393 if($plugins->current_hook) 394 { 395 $debug_extra = "<div style=\"float_right\">(Plugin Hook: {$plugins->current_hook})</div>"; 396 } 397 if(preg_match("#^\s*select#i", $string)) 398 { 399 $query = mysql_query("EXPLAIN $string", $this->current_link); 400 $this->explain .= "<table style=\"background-color: #666;\" width=\"95%\" cellpadding=\"4\" cellspacing=\"1\" align=\"center\">\n". 401 "<tr>\n". 402 "<td colspan=\"8\" style=\"background-color: #ccc;\">{$debug_extra}<div><strong>#".$this->query_count." - Select Query</strong></div></td>\n". 403 "</tr>\n". 404 "<tr>\n". 405 "<td colspan=\"8\" style=\"background-color: #fefefe;\"><span style=\"font-family: Courier; font-size: 14px;\">".htmlspecialchars_uni($string)."</span></td>\n". 406 "</tr>\n". 407 "<tr style=\"background-color: #efefef;\">\n". 408 "<td><strong>Table</strong></td>\n". 409 "<td><strong>Type</strong></td>\n". 410 "<td><strong>Possible Keys</strong></td>\n". 411 "<td><strong>Key</strong></td>\n". 412 "<td><strong>Key Length</strong></td>\n". 413 "<td><strong>Ref</strong></td>\n". 414 "<td><strong>Rows</strong></td>\n". 415 "<td><strong>Extra</strong></td>\n". 416 "</tr>\n"; 417 418 while($table = mysql_fetch_array($query)) 419 { 420 $this->explain .= 421 "<tr bgcolor=\"#ffffff\">\n". 422 "<td>".$table['table']."</td>\n". 423 "<td>".$table['type']."</td>\n". 424 "<td>".$table['possible_keys']."</td>\n". 425 "<td>".$table['key']."</td>\n". 426 "<td>".$table['key_len']."</td>\n". 427 "<td>".$table['ref']."</td>\n". 428 "<td>".$table['rows']."</td>\n". 429 "<td>".$table['Extra']."</td>\n". 430 "</tr>\n"; 431 } 432 $this->explain .= 433 "<tr>\n". 434 "<td colspan=\"8\" style=\"background-color: #fff;\">Query Time: ".format_time_duration($qtime)."</td>\n". 435 "</tr>\n". 436 "</table>\n". 437 "<br />\n"; 438 } 439 else 440 { 441 $this->explain .= "<table style=\"background-color: #666;\" width=\"95%\" cellpadding=\"4\" cellspacing=\"1\" align=\"center\">\n". 442 "<tr>\n". 443 "<td style=\"background-color: #ccc;\">{$debug_extra}<div><strong>#".$this->query_count." - Write Query</strong></div></td>\n". 444 "</tr>\n". 445 "<tr style=\"background-color: #fefefe;\">\n". 446 "<td><span style=\"font-family: Courier; font-size: 14px;\">".htmlspecialchars_uni($string)."</span></td>\n". 447 "</tr>\n". 448 "<tr>\n". 449 "<td bgcolor=\"#ffffff\">Query Time: ".format_time_duration($qtime)."</td>\n". 450 "</tr>\n". 451 "</table>\n". 452 "<br />\n"; 453 } 454 455 $this->querylist[$this->query_count]['query'] = $string; 456 $this->querylist[$this->query_count]['time'] = $qtime; 457 } 458 459 /** 460 * Return a result array for a query. 461 * 462 * @param resource $query The query ID. 463 * @param int $resulttype The type of array to return. Either MYSQL_NUM, MYSQL_BOTH or MYSQL_ASSOC 464 * @return array The array of results. 465 */ 466 function fetch_array($query, $resulttype=MYSQL_ASSOC) 467 { 468 switch($resulttype) 469 { 470 case MYSQL_NUM: 471 case MYSQL_BOTH: 472 break; 473 default: 474 $resulttype = MYSQL_ASSOC; 475 break; 476 } 477 478 $array = mysql_fetch_array($query, $resulttype); 479 480 return $array; 481 } 482 483 /** 484 * Return a specific field from a query. 485 * 486 * @param resource $query The query ID. 487 * @param string $field The name of the field to return. 488 * @param int|bool $row The number of the row to fetch it from. 489 * @return mixed 490 */ 491 function fetch_field($query, $field, $row=false) 492 { 493 if($row === false) 494 { 495 $array = $this->fetch_array($query); 496 if($array !== null) 497 { 498 return $array[$field]; 499 } 500 return null; 501 } 502 else 503 { 504 return mysql_result($query, $row, $field); 505 } 506 } 507 508 /** 509 * Moves internal row pointer to the next row 510 * 511 * @param resource $query The query ID. 512 * @param int $row The pointer to move the row to. 513 * @return bool 514 */ 515 function data_seek($query, $row) 516 { 517 return mysql_data_seek($query, $row); 518 } 519 520 /** 521 * Return the number of rows resulting from a query. 522 * 523 * @param resource $query The query ID. 524 * @return int The number of rows in the result. 525 */ 526 function num_rows($query) 527 { 528 return mysql_num_rows($query); 529 } 530 531 /** 532 * Return the last id number of inserted data. 533 * 534 * @return int The id number. 535 */ 536 function insert_id() 537 { 538 return mysql_insert_id($this->current_link); 539 } 540 541 /** 542 * Close the connection with the DBMS. 543 * 544 */ 545 function close() 546 { 547 @mysql_close($this->read_link); 548 if($this->write_link) 549 { 550 @mysql_close($this->write_link); 551 } 552 } 553 554 /** 555 * Return an error number. 556 * 557 * @return int The error number of the current error. 558 */ 559 function error_number() 560 { 561 if($this->current_link) 562 { 563 return @mysql_errno($this->current_link); 564 } 565 else 566 { 567 return @mysql_errno(); 568 } 569 } 570 571 /** 572 * Return an error string. 573 * 574 * @return string The explanation for the current error. 575 */ 576 function error_string() 577 { 578 if($this->current_link) 579 { 580 return @mysql_error($this->current_link); 581 } 582 else 583 { 584 return @mysql_error(); 585 } 586 } 587 588 /** 589 * Output a database error. 590 * 591 * @param string $string The string to present as an error. 592 * @return bool Returns false if error reporting is disabled, otherwise true 593 */ 594 function error($string="") 595 { 596 if($this->error_reporting) 597 { 598 if(class_exists("errorHandler")) 599 { 600 global $error_handler; 601 602 if(!is_object($error_handler)) 603 { 604 require_once MYBB_ROOT."inc/class_error.php"; 605 $error_handler = new errorHandler(); 606 } 607 608 $error = array( 609 "error_no" => $this->error_number(), 610 "error" => $this->error_string(), 611 "query" => $string 612 ); 613 $error_handler->error(MYBB_SQL, $error); 614 } 615 else 616 { 617 trigger_error("<strong>[SQL] [".$this->error_number()."] ".$this->error_string()."</strong><br />{$string}", E_USER_ERROR); 618 } 619 620 return true; 621 } 622 else 623 { 624 return false; 625 } 626 } 627 628 /** 629 * Returns the number of affected rows in a query. 630 * 631 * @return int The number of affected rows. 632 */ 633 function affected_rows() 634 { 635 return mysql_affected_rows($this->current_link); 636 } 637 638 /** 639 * Return the number of fields. 640 * 641 * @param resource $query The query ID. 642 * @return int The number of fields. 643 */ 644 function num_fields($query) 645 { 646 return mysql_num_fields($query); 647 } 648 649 /** 650 * Lists all tables in the database. 651 * 652 * @param string $database The database name. 653 * @param string $prefix Prefix of the table (optional) 654 * @return array The table list. 655 */ 656 function list_tables($database, $prefix='') 657 { 658 if($prefix) 659 { 660 if(version_compare($this->get_version(), '5.0.2', '>=')) 661 { 662 $query = $this->query("SHOW FULL TABLES FROM `$database` WHERE table_type = 'BASE TABLE' AND `Tables_in_$database` LIKE '".$this->escape_string($prefix)."%'"); 663 } 664 else 665 { 666 $query = $this->query("SHOW TABLES FROM `$database` LIKE '".$this->escape_string($prefix)."%'"); 667 } 668 } 669 else 670 { 671 if(version_compare($this->get_version(), '5.0.2', '>=')) 672 { 673 $query = $this->query("SHOW FULL TABLES FROM `$database` WHERE table_type = 'BASE TABLE'"); 674 } 675 else 676 { 677 $query = $this->query("SHOW TABLES FROM `$database`"); 678 } 679 } 680 681 $tables = array(); 682 while(list($table) = mysql_fetch_array($query)) 683 { 684 $tables[] = $table; 685 } 686 687 return $tables; 688 } 689 690 /** 691 * Check if a table exists in a database. 692 * 693 * @param string $table The table name. 694 * @return boolean True when exists, false if not. 695 */ 696 function table_exists($table) 697 { 698 // Execute on master server to ensure if we've just created a table that we get the correct result 699 if(version_compare($this->get_version(), '5.0.2', '>=')) 700 { 701 $query = $this->query("SHOW FULL TABLES FROM `".$this->database."` WHERE table_type = 'BASE TABLE' AND `Tables_in_".$this->database."` = '{$this->table_prefix}$table'"); 702 } 703 else 704 { 705 $query = $this->query("SHOW TABLES LIKE '{$this->table_prefix}$table'"); 706 } 707 708 $exists = $this->num_rows($query); 709 if($exists > 0) 710 { 711 return true; 712 } 713 else 714 { 715 return false; 716 } 717 } 718 719 /** 720 * Check if a field exists in a database. 721 * 722 * @param string $field The field name. 723 * @param string $table The table name. 724 * @return boolean True when exists, false if not. 725 */ 726 function field_exists($field, $table) 727 { 728 $query = $this->write_query(" 729 SHOW COLUMNS 730 FROM {$this->table_prefix}$table 731 LIKE '$field' 732 "); 733 $exists = $this->num_rows($query); 734 if($exists > 0) 735 { 736 return true; 737 } 738 else 739 { 740 return false; 741 } 742 } 743 744 /** 745 * Add a shutdown query. 746 * 747 * @param resource $query The query data. 748 * @param string $name An optional name for the query. 749 */ 750 function shutdown_query($query, $name="") 751 { 752 global $shutdown_queries; 753 if($name) 754 { 755 $shutdown_queries[$name] = $query; 756 } 757 else 758 { 759 $shutdown_queries[] = $query; 760 } 761 } 762 /** 763 * Performs a simple select query. 764 * 765 * @param string $table The table name to be queried. 766 * @param string $fields Comma delimetered list of fields to be selected. 767 * @param string $conditions SQL formatted list of conditions to be matched. 768 * @param array $options List of options: group by, order by, order direction, limit, limit start. 769 * @return resource The query data. 770 */ 771 function simple_select($table, $fields="*", $conditions="", $options=array()) 772 { 773 $query = "SELECT ".$fields." FROM {$this->table_prefix}{$table}"; 774 if($conditions != "") 775 { 776 $query .= " WHERE ".$conditions; 777 } 778 779 if(isset($options['group_by'])) 780 { 781 $query .= " GROUP BY ".$options['group_by']; 782 } 783 784 if(isset($options['order_by'])) 785 { 786 $query .= " ORDER BY ".$options['order_by']; 787 if(isset($options['order_dir'])) 788 { 789 $query .= " ".my_strtoupper($options['order_dir']); 790 } 791 } 792 793 if(isset($options['limit_start']) && isset($options['limit'])) 794 { 795 $query .= " LIMIT ".$options['limit_start'].", ".$options['limit']; 796 } 797 elseif(isset($options['limit'])) 798 { 799 $query .= " LIMIT ".$options['limit']; 800 } 801 802 return $this->query($query); 803 } 804 805 /** 806 * Build an insert query from an array. 807 * 808 * @param string $table The table name to perform the query on. 809 * @param array $array An array of fields and their values. 810 * @return int The insert ID if available 811 */ 812 function insert_query($table, $array) 813 { 814 global $mybb; 815 816 if(!is_array($array)) 817 { 818 return false; 819 } 820 821 foreach($array as $field => $value) 822 { 823 if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) 824 { 825 if($value[0] != 'X') // Not escaped? 826 { 827 $value = $this->escape_binary($value); 828 } 829 830 $array[$field] = $value; 831 } 832 else 833 { 834 $array[$field] = $this->quote_val($value); 835 } 836 } 837 838 $fields = "`".implode("`,`", array_keys($array))."`"; 839 $values = implode(",", $array); 840 $this->write_query(" 841 INSERT 842 INTO {$this->table_prefix}{$table} (".$fields.") 843 VALUES (".$values.") 844 "); 845 return $this->insert_id(); 846 } 847 848 /** 849 * Build one query for multiple inserts from a multidimensional array. 850 * 851 * @param string $table The table name to perform the query on. 852 * @param array $array An array of inserts. 853 * @return void 854 */ 855 function insert_query_multiple($table, $array) 856 { 857 global $mybb; 858 859 if(!is_array($array)) 860 { 861 return; 862 } 863 864 // Field names 865 $fields = array_keys($array[0]); 866 $fields = "`".implode("`,`", $fields)."`"; 867 868 $insert_rows = array(); 869 foreach($array as $values) 870 { 871 foreach($values as $field => $value) 872 { 873 if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) 874 { 875 if($value[0] != 'X') // Not escaped? 876 { 877 $value = $this->escape_binary($value); 878 } 879 880 $values[$field] = $value; 881 } 882 else 883 { 884 $values[$field] = $this->quote_val($value); 885 } 886 } 887 $insert_rows[] = "(".implode(",", $values).")"; 888 } 889 $insert_rows = implode(", ", $insert_rows); 890 891 $this->write_query(" 892 INSERT 893 INTO {$this->table_prefix}{$table} ({$fields}) 894 VALUES {$insert_rows} 895 "); 896 } 897 898 /** 899 * Build an update query from an array. 900 * 901 * @param string $table The table name to perform the query on. 902 * @param array $array An array of fields and their values. 903 * @param string $where An optional where clause for the query. 904 * @param string $limit An optional limit clause for the query. 905 * @param boolean $no_quote An option to quote incoming values of the array. 906 * @return resource The query data. 907 */ 908 function update_query($table, $array, $where="", $limit="", $no_quote=false) 909 { 910 global $mybb; 911 912 if(!is_array($array)) 913 { 914 return false; 915 } 916 917 $comma = ""; 918 $query = ""; 919 $quote = "'"; 920 921 if($no_quote == true) 922 { 923 $quote = ""; 924 } 925 926 foreach($array as $field => $value) 927 { 928 if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) 929 { 930 if($value[0] != 'X') // Not escaped? 931 { 932 $value = $this->escape_binary($value); 933 } 934 935 $query .= $comma."`".$field."`={$value}"; 936 } 937 else 938 { 939 $quoted_val = $this->quote_val($value, $quote); 940 941 $query .= $comma."`".$field."`={$quoted_val}"; 942 } 943 $comma = ', '; 944 } 945 946 if(!empty($where)) 947 { 948 $query .= " WHERE $where"; 949 } 950 951 if(!empty($limit)) 952 { 953 $query .= " LIMIT $limit"; 954 } 955 956 return $this->write_query(" 957 UPDATE {$this->table_prefix}$table 958 SET $query 959 "); 960 } 961 962 /** 963 * @param int|string $value 964 * @param string $quote 965 * 966 * @return int|string 967 */ 968 private function quote_val($value, $quote="'") 969 { 970 if(is_int($value)) 971 { 972 $quoted = $value; 973 } 974 else 975 { 976 $quoted = $quote . $value . $quote; 977 } 978 979 return $quoted; 980 } 981 982 /** 983 * Build a delete query. 984 * 985 * @param string $table The table name to perform the query on. 986 * @param string $where An optional where clause for the query. 987 * @param string $limit An optional limit clause for the query. 988 * @return resource The query data. 989 */ 990 function delete_query($table, $where="", $limit="") 991 { 992 $query = ""; 993 if(!empty($where)) 994 { 995 $query .= " WHERE $where"; 996 } 997 998 if(!empty($limit)) 999 { 1000 $query .= " LIMIT $limit"; 1001 } 1002 1003 return $this->write_query(" 1004 DELETE 1005 FROM {$this->table_prefix}$table 1006 $query 1007 "); 1008 } 1009 1010 /** 1011 * Escape a string according to the MySQL escape format. 1012 * 1013 * @param string $string The string to be escaped. 1014 * @return string The escaped string. 1015 */ 1016 function escape_string($string) 1017 { 1018 if($this->db_encoding == 'utf8') 1019 { 1020 $string = validate_utf8_string($string, false); 1021 } 1022 elseif($this->db_encoding == 'utf8mb4') 1023 { 1024 $string = validate_utf8_string($string); 1025 } 1026 1027 if(function_exists("mysql_real_escape_string") && $this->read_link) 1028 { 1029 $string = mysql_real_escape_string($string, $this->read_link); 1030 } 1031 else 1032 { 1033 $string = addslashes($string); 1034 } 1035 return $string; 1036 } 1037 1038 /** 1039 * Frees the resources of a MySQLi query. 1040 * 1041 * @param resource $query The query to destroy. 1042 * @return boolean Returns true on success, false on faliure 1043 */ 1044 function free_result($query) 1045 { 1046 return mysql_free_result($query); 1047 } 1048 1049 /** 1050 * Escape a string used within a like command. 1051 * 1052 * @param string $string The string to be escaped. 1053 * @return string The escaped string. 1054 */ 1055 function escape_string_like($string) 1056 { 1057 return $this->escape_string(str_replace(array('\\', '%', '_') , array('\\\\', '\\%' , '\\_') , $string)); 1058 } 1059 1060 /** 1061 * Gets the current version of MySQL. 1062 * 1063 * @return string Version of MySQL. 1064 */ 1065 function get_version() 1066 { 1067 if($this->version) 1068 { 1069 return $this->version; 1070 } 1071 1072 $query = $this->query("SELECT VERSION() as version"); 1073 $ver = $this->fetch_array($query); 1074 $version = $ver['version']; 1075 1076 if($version) 1077 { 1078 $version = explode(".", $version, 3); 1079 $this->version = (int)$version[0].".".(int)$version[1].".".(int)$version[2]; 1080 } 1081 return $this->version; 1082 } 1083 1084 /** 1085 * Optimizes a specific table. 1086 * 1087 * @param string $table The name of the table to be optimized. 1088 */ 1089 function optimize_table($table) 1090 { 1091 $this->write_query("OPTIMIZE TABLE {$this->table_prefix}{$table}"); 1092 } 1093 1094 /** 1095 * Analyzes a specific table. 1096 * 1097 * @param string $table The name of the table to be analyzed. 1098 */ 1099 function analyze_table($table) 1100 { 1101 $this->write_query("ANALYZE TABLE {$this->table_prefix}{$table}"); 1102 } 1103 1104 /** 1105 * Show the "create table" command for a specific table. 1106 * 1107 * @param string $table The name of the table. 1108 * @return string The MySQL command to create the specified table. 1109 */ 1110 function show_create_table($table) 1111 { 1112 $query = $this->write_query("SHOW CREATE TABLE {$this->table_prefix}{$table}"); 1113 $structure = $this->fetch_array($query); 1114 return $structure['Create Table']; 1115 } 1116 1117 /** 1118 * Show the "show fields from" command for a specific table. 1119 * 1120 * @param string $table The name of the table. 1121 * @return array Field info for that table 1122 */ 1123 function show_fields_from($table) 1124 { 1125 $query = $this->write_query("SHOW FIELDS FROM {$this->table_prefix}{$table}"); 1126 $field_info = array(); 1127 while($field = $this->fetch_array($query)) 1128 { 1129 $field_info[] = $field; 1130 } 1131 return $field_info; 1132 } 1133 1134 /** 1135 * Returns whether or not the table contains a fulltext index. 1136 * 1137 * @param string $table The name of the table. 1138 * @param string $index Optionally specify the name of the index. 1139 * @return boolean True or false if the table has a fulltext index or not. 1140 */ 1141 function is_fulltext($table, $index="") 1142 { 1143 $structure = $this->show_create_table($table); 1144 if($index != "") 1145 { 1146 if(preg_match("#FULLTEXT KEY (`?)$index(`?)#i", $structure)) 1147 { 1148 return true; 1149 } 1150 else 1151 { 1152 return false; 1153 } 1154 } 1155 if(preg_match('#FULLTEXT KEY#i', $structure)) 1156 { 1157 return true; 1158 } 1159 return false; 1160 } 1161 1162 /** 1163 * Returns whether or not this database engine supports fulltext indexing. 1164 * 1165 * @param string $table The table to be checked. 1166 * @return boolean True or false if supported or not. 1167 */ 1168 1169 function supports_fulltext($table) 1170 { 1171 $version = $this->get_version(); 1172 $query = $this->write_query("SHOW TABLE STATUS LIKE '{$this->table_prefix}$table'"); 1173 $status = $this->fetch_array($query); 1174 if($status['Engine']) 1175 { 1176 $table_type = my_strtoupper($status['Engine']); 1177 } 1178 else 1179 { 1180 $table_type = my_strtoupper($status['Type']); 1181 } 1182 if(version_compare($version, '3.23.23', '>=') && ($table_type == 'MYISAM' || $table_type == 'ARIA')) 1183 { 1184 return true; 1185 } 1186 elseif(version_compare($version, '5.6', '>=') && $table_type == 'INNODB') 1187 { 1188 return true; 1189 } 1190 return false; 1191 } 1192 1193 /** 1194 * Checks to see if an index exists on a specified table 1195 * 1196 * @param string $table The name of the table. 1197 * @param string $index The name of the index. 1198 * @return bool Whether or not the index exists in that table 1199 */ 1200 function index_exists($table, $index) 1201 { 1202 $index_exists = false; 1203 $query = $this->write_query("SHOW INDEX FROM {$this->table_prefix}{$table}"); 1204 while($ukey = $this->fetch_array($query)) 1205 { 1206 if($ukey['Key_name'] == $index) 1207 { 1208 $index_exists = true; 1209 break; 1210 } 1211 } 1212 1213 if($index_exists) 1214 { 1215 return true; 1216 } 1217 1218 return false; 1219 } 1220 1221 /** 1222 * Returns whether or not this database engine supports boolean fulltext matching. 1223 * 1224 * @param string $table The table to be checked. 1225 * @return boolean True or false if supported or not. 1226 */ 1227 function supports_fulltext_boolean($table) 1228 { 1229 $version = $this->get_version(); 1230 $supports_fulltext = $this->supports_fulltext($table); 1231 if(version_compare($version, '4.0.1', '>=') && $supports_fulltext == true) 1232 { 1233 return true; 1234 } 1235 return false; 1236 } 1237 1238 /** 1239 * Creates a fulltext index on the specified column in the specified table with optional index name. 1240 * 1241 * @param string $table The name of the table. 1242 * @param string $column Name of the column to be indexed. 1243 * @param string $name The index name, optional. 1244 */ 1245 function create_fulltext_index($table, $column, $name="") 1246 { 1247 $this->write_query(" 1248 ALTER TABLE {$this->table_prefix}$table 1249 ADD FULLTEXT $name ($column) 1250 "); 1251 } 1252 1253 /** 1254 * Drop an index with the specified name from the specified table 1255 * 1256 * @param string $table The name of the table. 1257 * @param string $name The name of the index. 1258 */ 1259 function drop_index($table, $name) 1260 { 1261 $this->write_query(" 1262 ALTER TABLE {$this->table_prefix}$table 1263 DROP INDEX $name 1264 "); 1265 } 1266 1267 /** 1268 * Drop an table with the specified table 1269 * 1270 * @param string $table The table to drop 1271 * @param boolean $hard hard drop - no checking 1272 * @param boolean $table_prefix use table prefix 1273 */ 1274 function drop_table($table, $hard=false, $table_prefix=true) 1275 { 1276 if($table_prefix == false) 1277 { 1278 $table_prefix = ""; 1279 } 1280 else 1281 { 1282 $table_prefix = $this->table_prefix; 1283 } 1284 1285 if($hard == false) 1286 { 1287 $this->write_query('DROP TABLE IF EXISTS '.$table_prefix.$table); 1288 } 1289 else 1290 { 1291 $this->write_query('DROP TABLE '.$table_prefix.$table); 1292 } 1293 } 1294 1295 /** 1296 * Renames a table 1297 * 1298 * @param string $old_table The old table name 1299 * @param string $new_table the new table name 1300 * @param boolean $table_prefix use table prefix 1301 * @return resource 1302 */ 1303 function rename_table($old_table, $new_table, $table_prefix=true) 1304 { 1305 if($table_prefix == false) 1306 { 1307 $table_prefix = ""; 1308 } 1309 else 1310 { 1311 $table_prefix = $this->table_prefix; 1312 } 1313 1314 return $this->write_query("RENAME TABLE {$table_prefix}{$old_table} TO {$table_prefix}{$new_table}"); 1315 } 1316 1317 /** 1318 * Replace contents of table with values 1319 * 1320 * @param string $table The table 1321 * @param array $replacements The replacements 1322 * @param string|array $default_field The default field(s) 1323 * @param boolean $insert_id Whether or not to return an insert id. True by default 1324 * @return resource|bool 1325 */ 1326 function replace_query($table, $replacements=array(), $default_field="", $insert_id=true) 1327 { 1328 global $mybb; 1329 1330 $values = ''; 1331 $comma = ''; 1332 foreach($replacements as $column => $value) 1333 { 1334 if(isset($mybb->binary_fields[$table][$column]) && $mybb->binary_fields[$table][$column]) 1335 { 1336 if($value[0] != 'X') // Not escaped? 1337 { 1338 $value = $this->escape_binary($value); 1339 } 1340 1341 $values .= $comma."`".$column."`=".$value; 1342 } 1343 else 1344 { 1345 $values .= $comma."`".$column."`=".$this->quote_val($value); 1346 } 1347 1348 $comma = ','; 1349 } 1350 1351 if(empty($replacements)) 1352 { 1353 return false; 1354 } 1355 1356 return $this->write_query("REPLACE INTO {$this->table_prefix}{$table} SET {$values}"); 1357 } 1358 1359 /** 1360 * Drops a column 1361 * 1362 * @param string $table The table 1363 * @param string $column The column name 1364 * @return resource 1365 */ 1366 function drop_column($table, $column) 1367 { 1368 $column = trim($column, '`'); 1369 1370 return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} DROP `{$column}`"); 1371 } 1372 1373 /** 1374 * Adds a column 1375 * 1376 * @param string $table The table 1377 * @param string $column The column name 1378 * @param string $definition the new column definition 1379 * @return resource 1380 */ 1381 function add_column($table, $column, $definition) 1382 { 1383 $column = trim($column, '`'); 1384 1385 return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ADD `{$column}` {$definition}"); 1386 } 1387 1388 /** 1389 * Modifies a column 1390 * 1391 * @param string $table The table 1392 * @param string $column The column name 1393 * @param string $new_definition the new column definition 1394 * @param boolean|string $new_not_null Whether to "drop" or "set" the NOT NULL attribute (no change if false) 1395 * @param boolean|string $new_default_value The new default value, or false to drop the attribute 1396 * @return bool Returns true if all queries are executed successfully or false if one of them failed 1397 */ 1398 function modify_column($table, $column, $new_definition, $new_not_null=false, $new_default_value=false) 1399 { 1400 $column = trim($column, '`'); 1401 1402 if($new_not_null !== false) 1403 { 1404 if(strtolower($new_not_null) == "set") 1405 { 1406 $not_null = "NOT NULL"; 1407 } 1408 else 1409 { 1410 $not_null = "NULL"; 1411 } 1412 } 1413 else 1414 { 1415 $not_null = ''; 1416 } 1417 1418 if($new_default_value !== false) 1419 { 1420 $default = "DEFAULT ".$new_default_value; 1421 } 1422 else 1423 { 1424 $default = ''; 1425 } 1426 1427 return (bool)$this->write_query("ALTER TABLE {$this->table_prefix}{$table} MODIFY `{$column}` {$new_definition} {$not_null} {$default}"); 1428 } 1429 1430 /** 1431 * Renames a column 1432 * 1433 * @param string $table The table 1434 * @param string $old_column The old column name 1435 * @param string $new_column the new column name 1436 * @param string $new_definition the new column definition 1437 * @param boolean|string $new_not_null Whether to "drop" or "set" the NOT NULL attribute (no change if false) 1438 * @param boolean|string $new_default_value The new default value, or false to drop the attribute 1439 * @return bool Returns true if all queries are executed successfully 1440 */ 1441 function rename_column($table, $old_column, $new_column, $new_definition, $new_not_null=false, $new_default_value=false) 1442 { 1443 $old_column = trim($old_column, '`'); 1444 $new_column = trim($new_column, '`'); 1445 1446 if($new_not_null !== false) 1447 { 1448 if(strtolower($new_not_null) == "set") 1449 { 1450 $not_null = "NOT NULL"; 1451 } 1452 else 1453 { 1454 $not_null = "NULL"; 1455 } 1456 } 1457 else 1458 { 1459 $not_null = ''; 1460 } 1461 1462 if($new_default_value !== false) 1463 { 1464 $default = "DEFAULT ".$new_default_value; 1465 } 1466 else 1467 { 1468 $default = ''; 1469 } 1470 1471 return (bool)$this->write_query("ALTER TABLE {$this->table_prefix}{$table} CHANGE `{$old_column}` `{$new_column}` {$new_definition} {$not_null} {$default}"); 1472 } 1473 1474 /** 1475 * Sets the table prefix used by the simple select, insert, update and delete functions 1476 * 1477 * @param string $prefix The new table prefix 1478 */ 1479 function set_table_prefix($prefix) 1480 { 1481 $this->table_prefix = $prefix; 1482 } 1483 1484 /** 1485 * Fetched the total size of all mysql tables or a specific table 1486 * 1487 * @param string $table The table (optional) 1488 * @return integer the total size of all mysql tables or a specific table 1489 */ 1490 function fetch_size($table='') 1491 { 1492 if($table != '') 1493 { 1494 $query = $this->query("SHOW TABLE STATUS LIKE '".$this->table_prefix.$table."'"); 1495 } 1496 else 1497 { 1498 $query = $this->query("SHOW TABLE STATUS"); 1499 } 1500 $total = 0; 1501 while($table = $this->fetch_array($query)) 1502 { 1503 $total += $table['Data_length']+$table['Index_length']; 1504 } 1505 return $total; 1506 } 1507 1508 /** 1509 * Fetch a list of database character sets this DBMS supports 1510 * 1511 * @return array|bool Array of supported character sets with array key being the name, array value being display name. False if unsupported 1512 */ 1513 function fetch_db_charsets() 1514 { 1515 if($this->write_link && version_compare($this->get_version(), "4.1", "<")) 1516 { 1517 return false; 1518 } 1519 return array( 1520 'big5' => 'Big5 Traditional Chinese', 1521 'dec8' => 'DEC West European', 1522 'cp850' => 'DOS West European', 1523 'hp8' => 'HP West European', 1524 'koi8r' => 'KOI8-R Relcom Russian', 1525 'latin1' => 'ISO 8859-1 Latin 1', 1526 'latin2' => 'ISO 8859-2 Central European', 1527 'swe7' => '7bit Swedish', 1528 'ascii' => 'US ASCII', 1529 'ujis' => 'EUC-JP Japanese', 1530 'sjis' => 'Shift-JIS Japanese', 1531 'hebrew' => 'ISO 8859-8 Hebrew', 1532 'tis620' => 'TIS620 Thai', 1533 'euckr' => 'EUC-KR Korean', 1534 'koi8u' => 'KOI8-U Ukrainian', 1535 'gb2312' => 'GB2312 Simplified Chinese', 1536 'greek' => 'ISO 8859-7 Greek', 1537 'cp1250' => 'Windows Central European', 1538 'gbk' => 'GBK Simplified Chinese', 1539 'latin5' => 'ISO 8859-9 Turkish', 1540 'armscii8' => 'ARMSCII-8 Armenian', 1541 'utf8' => 'UTF-8 Unicode', 1542 'utf8mb4' => '4-Byte UTF-8 Unicode (requires MySQL 5.5.3 or above)', 1543 'ucs2' => 'UCS-2 Unicode', 1544 'cp866' => 'DOS Russian', 1545 'keybcs2' => 'DOS Kamenicky Czech-Slovak', 1546 'macce' => 'Mac Central European', 1547 'macroman' => 'Mac West European', 1548 'cp852' => 'DOS Central European', 1549 'latin7' => 'ISO 8859-13 Baltic', 1550 'cp1251' => 'Windows Cyrillic', 1551 'cp1256' => 'Windows Arabic', 1552 'cp1257' => 'Windows Baltic', 1553 'geostd8' => 'GEOSTD8 Georgian', 1554 'cp932' => 'SJIS for Windows Japanese', 1555 'eucjpms' => 'UJIS for Windows Japanese', 1556 ); 1557 } 1558 1559 /** 1560 * Fetch a database collation for a particular database character set 1561 * 1562 * @param string $charset The database character set 1563 * @return string|bool The matching database collation, false if unsupported 1564 */ 1565 function fetch_charset_collation($charset) 1566 { 1567 $collations = array( 1568 'big5' => 'big5_chinese_ci', 1569 'dec8' => 'dec8_swedish_ci', 1570 'cp850' => 'cp850_general_ci', 1571 'hp8' => 'hp8_english_ci', 1572 'koi8r' => 'koi8r_general_ci', 1573 'latin1' => 'latin1_swedish_ci', 1574 'latin2' => 'latin2_general_ci', 1575 'swe7' => 'swe7_swedish_ci', 1576 'ascii' => 'ascii_general_ci', 1577 'ujis' => 'ujis_japanese_ci', 1578 'sjis' => 'sjis_japanese_ci', 1579 'hebrew' => 'hebrew_general_ci', 1580 'tis620' => 'tis620_thai_ci', 1581 'euckr' => 'euckr_korean_ci', 1582 'koi8u' => 'koi8u_general_ci', 1583 'gb2312' => 'gb2312_chinese_ci', 1584 'greek' => 'greek_general_ci', 1585 'cp1250' => 'cp1250_general_ci', 1586 'gbk' => 'gbk_chinese_ci', 1587 'latin5' => 'latin5_turkish_ci', 1588 'armscii8' => 'armscii8_general_ci', 1589 'utf8' => 'utf8_general_ci', 1590 'utf8mb4' => 'utf8mb4_general_ci', 1591 'ucs2' => 'ucs2_general_ci', 1592 'cp866' => 'cp866_general_ci', 1593 'keybcs2' => 'keybcs2_general_ci', 1594 'macce' => 'macce_general_ci', 1595 'macroman' => 'macroman_general_ci', 1596 'cp852' => 'cp852_general_ci', 1597 'latin7' => 'latin7_general_ci', 1598 'cp1251' => 'cp1251_general_ci', 1599 'cp1256' => 'cp1256_general_ci', 1600 'cp1257' => 'cp1257_general_ci', 1601 'geostd8' => 'geostd8_general_ci', 1602 'cp932' => 'cp932_japanese_ci', 1603 'eucjpms' => 'eucjpms_japanese_ci', 1604 ); 1605 if($collations[$charset]) 1606 { 1607 return $collations[$charset]; 1608 } 1609 return false; 1610 } 1611 1612 /** 1613 * Fetch a character set/collation string for use with CREATE TABLE statements. Uses current DB encoding 1614 * 1615 * @return string The built string, empty if unsupported 1616 */ 1617 function build_create_table_collation() 1618 { 1619 if(!$this->db_encoding) 1620 { 1621 return ''; 1622 } 1623 1624 $collation = $this->fetch_charset_collation($this->db_encoding); 1625 if(!$collation) 1626 { 1627 return ''; 1628 } 1629 return " CHARACTER SET {$this->db_encoding} COLLATE {$collation}"; 1630 } 1631 1632 /** 1633 * Time how long it takes for a particular piece of code to run. Place calls above & below the block of code. 1634 * 1635 * @deprecated 1636 */ 1637 function get_execution_time() 1638 { 1639 return get_execution_time(); 1640 } 1641 1642 /** 1643 * Binary database fields require special attention. 1644 * 1645 * @param string $string Binary value 1646 * @return string Encoded binary value 1647 */ 1648 function escape_binary($string) 1649 { 1650 return "X'".$this->escape_string(bin2hex($string))."'"; 1651 } 1652 1653 /** 1654 * Unescape binary data. 1655 * 1656 * @param string $string Binary value 1657 * @return string Encoded binary value 1658 */ 1659 function unescape_binary($string) 1660 { 1661 // Nothing to do 1662 return $string; 1663 } 1664 } 1665
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup | Cross-referenced by PHPXref |