Mercurial > hg > vamp-website
diff forum/Sources/DbExtra-mysql.php @ 76:e3e11437ecea website
Add forum code
author | Chris Cannam |
---|---|
date | Sun, 07 Jul 2013 11:25:48 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/forum/Sources/DbExtra-mysql.php Sun Jul 07 11:25:48 2013 +0200 @@ -0,0 +1,454 @@ +<?php + +/** + * Simple Machines Forum (SMF) + * + * @package SMF + * @author Simple Machines http://www.simplemachines.org + * @copyright 2011 Simple Machines + * @license http://www.simplemachines.org/about/smf/license.php BSD + * + * @version 2.0 + */ + +if (!defined('SMF')) + die('Hacking attempt...'); + +/* This file contains rarely used extended database functionality. + + void db_extra_init() + - add this file's functions to the $smcFunc array. + + resource smf_db_backup_table($table, $backup_table) + - backup $table to $backup_table. + - returns the request handle to the table creation query + + string function smf_db_get_version() + - get the version number. + + string db_insert_sql(string table_name) + - gets all the necessary INSERTs for the table named table_name. + - goes in 250 row segments. + - returns the query to insert the data back in. + - returns an empty string if the table was empty. + + array smf_db_list_tables($db = false, $filter = false) + - lists all tables in the database + - could be filtered according to $filter + - returns an array of table names. (strings) + + float smf_db_optimize_table($table) + - optimize a table + - $table - the table to be optimized + - returns how much it was gained + + string db_table_sql(string table_name) + - dumps the CREATE for the specified table. (by table_name.) + - returns the CREATE statement. + +*/ + +// Add the file functions to the $smcFunc array. +function db_extra_init() +{ + global $smcFunc; + + if (!isset($smcFunc['db_backup_table']) || $smcFunc['db_backup_table'] != 'smf_db_backup_table') + $smcFunc += array( + 'db_backup_table' => 'smf_db_backup_table', + 'db_optimize_table' => 'smf_db_optimize_table', + 'db_insert_sql' => 'smf_db_insert_sql', + 'db_table_sql' => 'smf_db_table_sql', + 'db_list_tables' => 'smf_db_list_tables', + 'db_get_version' => 'smf_db_get_version', + ); +} + +// Backup $table to $backup_table. +function smf_db_backup_table($table, $backup_table) +{ + global $smcFunc, $db_prefix; + + $table = str_replace('{db_prefix}', $db_prefix, $table); + + // First, get rid of the old table. + $smcFunc['db_query']('', ' + DROP TABLE IF EXISTS {raw:backup_table}', + array( + 'backup_table' => $backup_table, + ) + ); + + // Can we do this the quick way? + $result = $smcFunc['db_query']('', ' + CREATE TABLE {raw:backup_table} LIKE {raw:table}', + array( + 'backup_table' => $backup_table, + 'table' => $table + )); + // If this failed, we go old school. + if ($result) + { + $request = $smcFunc['db_query']('', ' + INSERT INTO {raw:backup_table} + SELECT * + FROM {raw:table}', + array( + 'backup_table' => $backup_table, + 'table' => $table + )); + + // Old school or no school? + if ($request) + return $request; + } + + // At this point, the quick method failed. + $result = $smcFunc['db_query']('', ' + SHOW CREATE TABLE {raw:table}', + array( + 'table' => $table, + ) + ); + list (, $create) = $smcFunc['db_fetch_row']($result); + $smcFunc['db_free_result']($result); + + $create = preg_split('/[\n\r]/', $create); + + $auto_inc = ''; + // Default engine type. + $engine = 'MyISAM'; + $charset = ''; + $collate = ''; + + foreach ($create as $k => $l) + { + // Get the name of the auto_increment column. + if (strpos($l, 'auto_increment')) + $auto_inc = trim($l); + + // For the engine type, see if we can work out what it is. + if (strpos($l, 'ENGINE') !== false || strpos($l, 'TYPE') !== false) + { + // Extract the engine type. + preg_match('~(ENGINE|TYPE)=(\w+)(\sDEFAULT)?(\sCHARSET=(\w+))?(\sCOLLATE=(\w+))?~', $l, $match); + + if (!empty($match[1])) + $engine = $match[1]; + + if (!empty($match[2])) + $engine = $match[2]; + + if (!empty($match[5])) + $charset = $match[5]; + + if (!empty($match[7])) + $collate = $match[7]; + } + + // Skip everything but keys... + if (strpos($l, 'KEY') === false) + unset($create[$k]); + } + + if (!empty($create)) + $create = '( + ' . implode(' + ', $create) . ')'; + else + $create = ''; + + $request = $smcFunc['db_query']('', ' + CREATE TABLE {raw:backup_table} {raw:create} + ENGINE={raw:engine}' . (empty($charset) ? '' : ' CHARACTER SET {raw:charset}' . (empty($collate) ? '' : ' COLLATE {raw:collate}')) . ' + SELECT * + FROM {raw:table}', + array( + 'backup_table' => $backup_table, + 'table' => $table, + 'create' => $create, + 'engine' => $engine, + 'charset' => empty($charset) ? '' : $charset, + 'collate' => empty($collate) ? '' : $collate, + ) + ); + + if ($auto_inc != '') + { + if (preg_match('~\`(.+?)\`\s~', $auto_inc, $match) != 0 && substr($auto_inc, -1, 1) == ',') + $auto_inc = substr($auto_inc, 0, -1); + + $smcFunc['db_query']('', ' + ALTER TABLE {raw:backup_table} + CHANGE COLUMN {raw:column_detail} {raw:auto_inc}', + array( + 'backup_table' => $backup_table, + 'column_detail' => $match[1], + 'auto_inc' => $auto_inc, + ) + ); + } + + return $request; +} + +// Optimize a table - return data freed! +function smf_db_optimize_table($table) +{ + global $smcFunc, $db_name, $db_prefix; + + $table = str_replace('{db_prefix}', $db_prefix, $table); + + // Get how much overhead there is. + $request = $smcFunc['db_query']('', ' + SHOW TABLE STATUS LIKE {string:table_name}', + array( + 'table_name' => str_replace('_', '\_', $table), + ) + ); + $row = $smcFunc['db_fetch_assoc']($request); + $smcFunc['db_free_result']($request); + + $data_before = isset($row['Data_free']) ? $row['Data_free'] : 0; + $request = $smcFunc['db_query']('', ' + OPTIMIZE TABLE `{raw:table}`', + array( + 'table' => $table, + ) + ); + if (!$request) + return -1; + + // How much left? + $request = $smcFunc['db_query']('', ' + SHOW TABLE STATUS LIKE {string:table}', + array( + 'table' => str_replace('_', '\_', $table), + ) + ); + $row = $smcFunc['db_fetch_assoc']($request); + $smcFunc['db_free_result']($request); + + $total_change = isset($row['Data_free']) && $data_before > $row['Data_free'] ? $data_before / 1024 : 0; + + return $total_change; +} + +// List all the tables in the database. +function smf_db_list_tables($db = false, $filter = false) +{ + global $db_name, $smcFunc; + + $db = $db == false ? $db_name : $db; + $db = trim($db); + $filter = $filter == false ? '' : ' LIKE \'' . $filter . '\''; + + $request = $smcFunc['db_query']('', ' + SHOW TABLES + FROM `{raw:db}` + {raw:filter}', + array( + 'db' => $db[0] == '`' ? strtr($db, array('`' => '')) : $db, + 'filter' => $filter, + ) + ); + $tables = array(); + while ($row = $smcFunc['db_fetch_row']($request)) + $tables[] = $row[0]; + $smcFunc['db_free_result']($request); + + return $tables; +} + +// Get the content (INSERTs) for a table. +function smf_db_insert_sql($tableName) +{ + global $smcFunc, $db_prefix; + + $tableName = str_replace('{db_prefix}', $db_prefix, $tableName); + + // This will be handy... + $crlf = "\r\n"; + + // Get everything from the table. + $result = $smcFunc['db_query']('', ' + SELECT /*!40001 SQL_NO_CACHE */ * + FROM `{raw:table}`', + array( + 'table' => $tableName, + ) + ); + + // The number of rows, just for record keeping and breaking INSERTs up. + $num_rows = $smcFunc['db_num_rows']($result); + $current_row = 0; + + if ($num_rows == 0) + return ''; + + $fields = array_keys($smcFunc['db_fetch_assoc']($result)); + $smcFunc['db_data_seek']($result, 0); + + // Start it off with the basic INSERT INTO. + $data = 'INSERT INTO `' . $tableName . '`' . $crlf . "\t" . '(`' . implode('`, `', $fields) . '`)' . $crlf . 'VALUES '; + + // Loop through each row. + while ($row = $smcFunc['db_fetch_row']($result)) + { + $current_row++; + + // Get the fields in this row... + $field_list = array(); + for ($j = 0; $j < $smcFunc['db_num_fields']($result); $j++) + { + // Try to figure out the type of each field. (NULL, number, or 'string'.) + if (!isset($row[$j])) + $field_list[] = 'NULL'; + elseif (is_numeric($row[$j]) && (int) $row[$j] == $row[$j]) + $field_list[] = $row[$j]; + else + $field_list[] = '\'' . $smcFunc['db_escape_string']($row[$j]) . '\''; + } + + // 'Insert' the data. + $data .= '(' . implode(', ', $field_list) . ')'; + + // All done! + if ($current_row == $num_rows) + $data .= ';' . $crlf; + // Start a new INSERT statement after every 250.... + elseif ($current_row > 249 && $current_row % 250 == 0) + $data .= ';' . $crlf . 'INSERT INTO `' . $tableName . '`' . $crlf . "\t" . '(`' . implode('`, `', $fields) . '`)' . $crlf . 'VALUES '; + // Otherwise, go to the next line. + else + $data .= ',' . $crlf . "\t"; + } + $smcFunc['db_free_result']($result); + + // Return an empty string if there were no rows. + return $num_rows == 0 ? '' : $data; +} + +// Get the schema (CREATE) for a table. +function smf_db_table_sql($tableName) +{ + global $smcFunc, $db_prefix; + + $tableName = str_replace('{db_prefix}', $db_prefix, $tableName); + + // This will be needed... + $crlf = "\r\n"; + + // Drop it if it exists. + $schema_create = 'DROP TABLE IF EXISTS `' . $tableName . '`;' . $crlf . $crlf; + + // Start the create table... + $schema_create .= 'CREATE TABLE `' . $tableName . '` (' . $crlf; + + // Find all the fields. + $result = $smcFunc['db_query']('', ' + SHOW FIELDS + FROM `{raw:table}`', + array( + 'table' => $tableName, + ) + ); + while ($row = $smcFunc['db_fetch_assoc']($result)) + { + // Make the CREATE for this column. + $schema_create .= ' `' . $row['Field'] . '` ' . $row['Type'] . ($row['Null'] != 'YES' ? ' NOT NULL' : ''); + + // Add a default...? + if (!empty($row['Default']) || $row['Null'] !== 'YES') + { + // Make a special case of auto-timestamp. + if ($row['Default'] == 'CURRENT_TIMESTAMP') + $schema_create .= ' /*!40102 NOT NULL default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP */'; + // Text shouldn't have a default. + elseif ($row['Default'] !== null) + { + // If this field is numeric the default needs no escaping. + $type = strtolower($row['Type']); + $isNumericColumn = strpos($type, 'int') !== false || strpos($type, 'bool') !== false || strpos($type, 'bit') !== false || strpos($type, 'float') !== false || strpos($type, 'double') !== false || strpos($type, 'decimal') !== false; + + $schema_create .= ' default ' . ($isNumericColumn ? $row['Default'] : '\'' . $smcFunc['db_escape_string']($row['Default']) . '\''); + } + } + + // And now any extra information. (such as auto_increment.) + $schema_create .= ($row['Extra'] != '' ? ' ' . $row['Extra'] : '') . ',' . $crlf; + } + $smcFunc['db_free_result']($result); + + // Take off the last comma. + $schema_create = substr($schema_create, 0, -strlen($crlf) - 1); + + // Find the keys. + $result = $smcFunc['db_query']('', ' + SHOW KEYS + FROM `{raw:table}`', + array( + 'table' => $tableName, + ) + ); + $indexes = array(); + while ($row = $smcFunc['db_fetch_assoc']($result)) + { + // IS this a primary key, unique index, or regular index? + $row['Key_name'] = $row['Key_name'] == 'PRIMARY' ? 'PRIMARY KEY' : (empty($row['Non_unique']) ? 'UNIQUE ' : ($row['Comment'] == 'FULLTEXT' || (isset($row['Index_type']) && $row['Index_type'] == 'FULLTEXT') ? 'FULLTEXT ' : 'KEY ')) . '`' . $row['Key_name'] . '`'; + + // Is this the first column in the index? + if (empty($indexes[$row['Key_name']])) + $indexes[$row['Key_name']] = array(); + + // A sub part, like only indexing 15 characters of a varchar. + if (!empty($row['Sub_part'])) + $indexes[$row['Key_name']][$row['Seq_in_index']] = '`' . $row['Column_name'] . '`(' . $row['Sub_part'] . ')'; + else + $indexes[$row['Key_name']][$row['Seq_in_index']] = '`' . $row['Column_name'] . '`'; + } + $smcFunc['db_free_result']($result); + + // Build the CREATEs for the keys. + foreach ($indexes as $keyname => $columns) + { + // Ensure the columns are in proper order. + ksort($columns); + + $schema_create .= ',' . $crlf . ' ' . $keyname . ' (' . implode($columns, ', ') . ')'; + } + + // Now just get the comment and type... (MyISAM, etc.) + $result = $smcFunc['db_query']('', ' + SHOW TABLE STATUS + LIKE {string:table}', + array( + 'table' => strtr($tableName, array('_' => '\\_', '%' => '\\%')), + ) + ); + $row = $smcFunc['db_fetch_assoc']($result); + $smcFunc['db_free_result']($result); + + // Probably MyISAM.... and it might have a comment. + $schema_create .= $crlf . ') ENGINE=' . (isset($row['Type']) ? $row['Type'] : $row['Engine']) . ($row['Comment'] != '' ? ' COMMENT="' . $row['Comment'] . '"' : ''); + + return $schema_create; +} + +// Get the version number. +function smf_db_get_version() +{ + global $smcFunc; + + $request = $smcFunc['db_query']('', ' + SELECT VERSION()', + array( + ) + ); + list ($ver) = $smcFunc['db_fetch_row']($request); + $smcFunc['db_free_result']($request); + + return $ver; +} + +?> \ No newline at end of file