[ Index ]

PHP Cross Reference of MyBB 1.8.32

title

Body

[close]

/inc/ -> db_mysqli.php (source)

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


2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup Cross-referenced by PHPXref