current_hook) {
$debug_extra = <<(Plugin Hook: {$plugins->current_hook})
HTML;
}
if (preg_match('/^\\s*SELECT\\b/i', $string) === 1) {
$query = $this->current_link->query("EXPLAIN {$string}");
$this->explain .= <<
{$debug_extra} #{$this->query_count} - Select Query
|
{$queryText}
|
Table |
Type |
Possible Keys |
Key |
Key Length |
Ref |
Rows |
Extra |
HTML;
while ($table = $query->fetch(PDO::FETCH_ASSOC)) {
$this->explain .= <<
{$table['table']} |
{$table['type']} |
{$table['possible_keys']} |
{$table['key']} |
{$table['key_len']} |
{$table['ref']} |
{$table['rows']} |
{$table['Extra']} |
HTML;
}
$this->explain .= <<
Query Time: {$duration}
|
HTML;
} else {
$this->explain .= <<
{$debug_extra} #{$this->query_count} - Write Query
|
{$queryText} |
Query Time: {$duration} |
HTML;
}
$this->querylist[$this->query_count]['query'] = $string;
$this->querylist[$this->query_count]['time'] = $qtime;
}
public function list_tables($database, $prefix = '')
{
if ($prefix) {
if (version_compare($this->get_version(), '5.0.2', '>=')) {
$query = $this->query("SHOW FULL TABLES FROM `{$database}` WHERE table_type = 'BASE TABLE' AND `Tables_in_{$database}` LIKE '".$this->escape_string($prefix)."%'");
} else {
$query = $this->query("SHOW TABLES FROM `{$database}` LIKE '{$this->escape_string($prefix)}%'");
}
} else {
if (version_compare($this->get_version(), '5.0.2', '>=')) {
$query = $this->query("SHOW FULL TABLES FROM `{$database}` WHERE table_type = 'BASE TABLE'");
} else {
$query = $this->query("SHOW TABLES FROM `{$database}`");
}
}
return $query->fetchAll(PDO::FETCH_COLUMN, 0);
}
public function table_exists($table)
{
// Execute on master server to ensure if we've just created a table that we get the correct result
if (version_compare($this->get_version(), '5.0.2', '>=')) {
$query = $this->query("SHOW FULL TABLES FROM `{$this->database}` WHERE table_type = 'BASE TABLE' AND `Tables_in_{$this->database}` = '{$this->table_prefix}{$table}'");
} else {
$query = $this->query("SHOW TABLES LIKE '{$this->table_prefix}{$table}'");
}
$count = 0;
while ($row = $this->fetch_array($query)) {
$count++;
}
return $count > 0;
}
public function field_exists($field, $table)
{
$query = $this->write_query("
SHOW COLUMNS
FROM {$this->table_prefix}{$table}
LIKE '{$field}'
");
$exists = $this->num_rows($query);
return $exists > 0;
}
public function simple_select($table, $fields = "*", $conditions = "", $options = array())
{
$query = "SELECT {$fields} FROM {$this->table_prefix}{$table}";
if (!empty($conditions)) {
$query .= " WHERE {$conditions}";
}
if (isset($options['group_by'])) {
$query .= " GROUP BY {$options['group_by']}";
}
if (isset($options['order_by'])) {
$query .= " ORDER BY {$options['order_by']}";
if (isset($options['order_dir'])) {
$query .= " ".my_strtoupper($options['order_dir']);
}
}
if (isset($options['limit_start']) && isset($options['limit'])) {
$query .= " LIMIT {$options['limit_start']}, {$options['limit']}";
}
else if (isset($options['limit'])) {
$query .= " LIMIT {$options['limit']}";
}
return $this->query($query);
}
public function insert_query($table, $array)
{
global $mybb;
if (!is_array($array)) {
return false;
}
foreach ($array as $field => $value) {
if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) {
if ($value[0] != 'X') { // Not escaped?
$value = $this->escape_binary($value);
}
$array[$field] = $value;
} else {
$array[$field] = $this->quote_val($value);
}
}
$fields = "`".implode("`,`", array_keys($array))."`";
$values = implode(",", $array);
$this->write_query("
INSERT
INTO {$this->table_prefix}{$table} ({$fields})
VALUES ({$values})
");
return $this->insert_id();
}
public function insert_query_multiple($table, $array)
{
global $mybb;
if (!is_array($array)) {
return;
}
// Field names
$fields = array_keys($array[0]);
$fields = "`".implode("`,`", $fields)."`";
$insert_rows = array();
foreach ($array as $values) {
foreach ($values as $field => $value) {
if (isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) {
if($value[0] != 'X') { // Not escaped?
$value = $this->escape_binary($value);
}
$values[$field] = $value;
} else {
$values[$field] = $this->quote_val($value);
}
}
$insert_rows[] = "(".implode(",", $values).")";
}
$insert_rows = implode(", ", $insert_rows);
$this->write_query("
INSERT
INTO {$this->table_prefix}{$table} ({$fields})
VALUES {$insert_rows}
");
}
public function update_query($table, $array, $where = "", $limit = "", $no_quote = false)
{
global $mybb;
if (!is_array($array)) {
return false;
}
$comma = "";
$query = "";
$quote = "'";
if ($no_quote == true) {
$quote = "";
}
foreach ($array as $field => $value) {
if (isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) {
if($value[0] != 'X') { // Not escaped?
$value = $this->escape_binary($value);
}
$query .= "{$comma}`{$field}`={$value}";
} else {
$quoted_value = $this->quote_val($value, $quote);
$query .= "{$comma}`{$field}`={$quoted_value}";
}
$comma = ', ';
}
if (!empty($where)) {
$query .= " WHERE {$where}";
}
if (!empty($limit)) {
$query .= " LIMIT {$limit}";
}
return $this->write_query("
UPDATE {$this->table_prefix}{$table}
SET {$query}
");
}
public function delete_query($table, $where = "", $limit = "")
{
$query = "";
if (!empty($where)) {
$query .= " WHERE {$where}";
}
if (!empty($limit)) {
$query .= " LIMIT {$limit}";
}
return $this->write_query("DELETE FROM {$this->table_prefix}{$table} {$query}");
}
public function optimize_table($table)
{
$this->write_query("OPTIMIZE TABLE {$this->table_prefix}{$table}");
}
public function analyze_table($table)
{
$this->write_query("ANALYZE TABLE {$this->table_prefix}{$table}");
}
public function show_create_table($table)
{
$query = $this->write_query("SHOW CREATE TABLE {$this->table_prefix}{$table}");
$structure = $this->fetch_array($query);
return $structure['Create Table'];
}
public function show_fields_from($table)
{
$query = $this->write_query("SHOW FIELDS FROM {$this->table_prefix}{$table}");
$field_info = array();
while ($field = $this->fetch_array($query)) {
$field_info[] = $field;
}
return $field_info;
}
public function is_fulltext($table, $index = "")
{
$structure = $this->show_create_table($table);
if ($index != "") {
if(preg_match("#FULLTEXT KEY (`?){$index}(`?)#i", $structure)) {
return true;
}
return false;
}
if (preg_match('#FULLTEXT KEY#i', $structure)) {
return true;
}
return false;
}
public function supports_fulltext($table)
{
$version = $this->get_version();
$query = $this->write_query("SHOW TABLE STATUS LIKE '{$this->table_prefix}$table'");
$status = $this->fetch_array($query);
$table_type = my_strtoupper($status['Engine']);
if (version_compare($version, '3.23.23', '>=') && ($table_type == 'MYISAM' || $table_type == 'ARIA')) {
return true;
} else if (version_compare($version, '5.6', '>=') && $table_type == 'INNODB') {
return true;
}
return false;
}
public function index_exists($table, $index)
{
$index_exists = false;
$query = $this->write_query("SHOW INDEX FROM {$this->table_prefix}{$table}");
while ($ukey = $this->fetch_array($query)) {
if ($ukey['Key_name'] == $index) {
$index_exists = true;
break;
}
}
return $index_exists;
}
public function supports_fulltext_boolean($table)
{
$version = $this->get_version();
$supports_fulltext = $this->supports_fulltext($table);
if (version_compare($version, '4.0.1', '>=') && $supports_fulltext == true) {
return true;
}
return false;
}
public function create_fulltext_index($table, $column, $name = "")
{
$this->write_query("ALTER TABLE {$this->table_prefix}{$table} ADD FULLTEXT {$name} ({$column})");
}
public function drop_index($table, $name)
{
$this->write_query("ALTER TABLE {$this->table_prefix}{$table} DROP INDEX {$name}");
}
public function drop_table($table, $hard = false, $table_prefix = true)
{
if ($table_prefix == false) {
$table_prefix = "";
} else {
$table_prefix = $this->table_prefix;
}
if ($hard == false) {
$this->write_query("DROP TABLE IF EXISTS {$table_prefix}{$table}");
} else {
$this->write_query("DROP TABLE {$table_prefix}{$table}");
}
}
public function rename_table($old_table, $new_table, $table_prefix = true)
{
if ($table_prefix == false) {
$table_prefix = "";
} else {
$table_prefix = $this->table_prefix;
}
return $this->write_query("RENAME TABLE {$table_prefix}{$old_table} TO {$table_prefix}{$new_table}");
}
public function replace_query($table, $replacements = array(), $default_field = "", $insert_id = true)
{
global $mybb;
$values = '';
$comma = '';
foreach ($replacements as $column => $value) {
if (isset($mybb->binary_fields[$table][$column]) && $mybb->binary_fields[$table][$column]) {
if ($value[0] != 'X') { // Not escaped?
$value = $this->escape_binary($value);
}
$values .= $comma."`".$column."`=".$value;
} else {
$values .= $comma."`".$column."`=".$this->quote_val($value);
}
$comma = ',';
}
if (empty($replacements)) {
return false;
}
return $this->write_query("REPLACE INTO {$this->table_prefix}{$table} SET {$values}");
}
public function drop_column($table, $column)
{
$column = trim($column, '`');
return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} DROP `{$column}`");
}
public function add_column($table, $column, $definition)
{
$column = trim($column, '`');
return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ADD `{$column}` {$definition}");
}
public function modify_column($table, $column, $new_definition, $new_not_null = false, $new_default_value = false)
{
$column = trim($column, '`');
if ($new_not_null !== false) {
if (strtolower($new_not_null) == "set") {
$not_null = "NOT NULL";
} else {
$not_null = "NULL";
}
} else {
$not_null = '';
}
if ($new_default_value !== false) {
$default = "DEFAULT ".$new_default_value;
}
else
{
$default = '';
}
return (bool)$this->write_query("ALTER TABLE {$this->table_prefix}{$table} MODIFY `{$column}` {$new_definition} {$not_null} {$default}");
}
public function rename_column($table, $old_column, $new_column, $new_definition, $new_not_null = false, $new_default_value = false)
{
$old_column = trim($old_column, '`');
$new_column = trim($new_column, '`');
if ($new_not_null !== false) {
if(strtolower($new_not_null) == "set") {
$not_null = "NOT NULL";
} else {
$not_null = "NULL";
}
} else {
$not_null = '';
}
if ($new_default_value !== false) {
$default = "DEFAULT ".$new_default_value;
} else {
$default = '';
}
return (bool)$this->write_query("ALTER TABLE {$this->table_prefix}{$table} CHANGE `{$old_column}` `{$new_column}` {$new_definition} {$not_null} {$default}");
}
public function fetch_size($table = '')
{
if ($table != '') {
$query = $this->query("SHOW TABLE STATUS LIKE '{$this->table_prefix}{$table}'");
} else {
$query = $this->query("SHOW TABLE STATUS");
}
$total = 0;
while ($table = $this->fetch_array($query)) {
$total += $table['Data_length'] + $table['Index_length'];
}
return $total;
}
public function fetch_db_charsets()
{
if ($this->write_link && version_compare($this->get_version(), "4.1", "<")) {
return false;
}
return array(
'big5' => 'Big5 Traditional Chinese',
'dec8' => 'DEC West European',
'cp850' => 'DOS West European',
'hp8' => 'HP West European',
'koi8r' => 'KOI8-R Relcom Russian',
'latin1' => 'ISO 8859-1 Latin 1',
'latin2' => 'ISO 8859-2 Central European',
'swe7' => '7bit Swedish',
'ascii' => 'US ASCII',
'ujis' => 'EUC-JP Japanese',
'sjis' => 'Shift-JIS Japanese',
'hebrew' => 'ISO 8859-8 Hebrew',
'tis620' => 'TIS620 Thai',
'euckr' => 'EUC-KR Korean',
'koi8u' => 'KOI8-U Ukrainian',
'gb2312' => 'GB2312 Simplified Chinese',
'greek' => 'ISO 8859-7 Greek',
'cp1250' => 'Windows Central European',
'gbk' => 'GBK Simplified Chinese',
'latin5' => 'ISO 8859-9 Turkish',
'armscii8' => 'ARMSCII-8 Armenian',
'utf8' => 'UTF-8 Unicode',
'utf8mb4' => '4-Byte UTF-8 Unicode (requires MySQL 5.5.3 or above)',
'ucs2' => 'UCS-2 Unicode',
'cp866' => 'DOS Russian',
'keybcs2' => 'DOS Kamenicky Czech-Slovak',
'macce' => 'Mac Central European',
'macroman' => 'Mac West European',
'cp852' => 'DOS Central European',
'latin7' => 'ISO 8859-13 Baltic',
'cp1251' => 'Windows Cyrillic',
'cp1256' => 'Windows Arabic',
'cp1257' => 'Windows Baltic',
'geostd8' => 'GEOSTD8 Georgian',
'cp932' => 'SJIS for Windows Japanese',
'eucjpms' => 'UJIS for Windows Japanese',
);
}
public function fetch_charset_collation($charset)
{
$collations = array(
'big5' => 'big5_chinese_ci',
'dec8' => 'dec8_swedish_ci',
'cp850' => 'cp850_general_ci',
'hp8' => 'hp8_english_ci',
'koi8r' => 'koi8r_general_ci',
'latin1' => 'latin1_swedish_ci',
'latin2' => 'latin2_general_ci',
'swe7' => 'swe7_swedish_ci',
'ascii' => 'ascii_general_ci',
'ujis' => 'ujis_japanese_ci',
'sjis' => 'sjis_japanese_ci',
'hebrew' => 'hebrew_general_ci',
'tis620' => 'tis620_thai_ci',
'euckr' => 'euckr_korean_ci',
'koi8u' => 'koi8u_general_ci',
'gb2312' => 'gb2312_chinese_ci',
'greek' => 'greek_general_ci',
'cp1250' => 'cp1250_general_ci',
'gbk' => 'gbk_chinese_ci',
'latin5' => 'latin5_turkish_ci',
'armscii8' => 'armscii8_general_ci',
'utf8' => 'utf8_general_ci',
'utf8mb4' => 'utf8mb4_general_ci',
'ucs2' => 'ucs2_general_ci',
'cp866' => 'cp866_general_ci',
'keybcs2' => 'keybcs2_general_ci',
'macce' => 'macce_general_ci',
'macroman' => 'macroman_general_ci',
'cp852' => 'cp852_general_ci',
'latin7' => 'latin7_general_ci',
'cp1251' => 'cp1251_general_ci',
'cp1256' => 'cp1256_general_ci',
'cp1257' => 'cp1257_general_ci',
'geostd8' => 'geostd8_general_ci',
'cp932' => 'cp932_japanese_ci',
'eucjpms' => 'eucjpms_japanese_ci',
);
if (isset($collations[$charset])) {
return $collations[$charset];
}
return false;
}
public function build_create_table_collation()
{
if (!$this->db_encoding) {
return '';
}
$collation = $this->fetch_charset_collation($this->db_encoding);
if (!$collation) {
return '';
}
return " CHARACTER SET {$this->db_encoding} COLLATE {$collation}";
}
public function escape_binary($string)
{
return "X'{$this->escape_string(bin2hex($string))}'";
}
public function unescape_binary($string)
{
return $string;
}
/**
* @param int|string $value
* @param string $quote
*
* @return int|string
*/
private function quote_val($value, $quote="'")
{
if (is_int($value)) {
return $value;
}
return "{$quote}{$value}{$quote}";
}
public function __set($name, $value)
{
if ($name === 'type') {
// NOTE: This is to prevent the type being set - this type should appear as `mysqli` to ensure compatibility
return;
}
}
public function __get($name)
{
if ($name === 'type') {
// NOTE: this is to ensure compatibility checks on the DB type will work
return 'mysqli';
}
return null;
}
}