diff --git a/js/database/structure.js b/js/database/structure.js index b4886918d6..eec0b9861e 100644 --- a/js/database/structure.js +++ b/js/database/structure.js @@ -298,15 +298,15 @@ AJAX.registerOnload('database/structure.js', function () { } if (action === 'analyze_tbl') { - url = 'index.php?route=/database/structure/analyze-table'; + url = 'index.php?route=/table/maintenance/analyze'; } else if (action === 'sync_unique_columns_central_list') { url = 'index.php?route=/database/structure/central-columns-add'; } else if (action === 'delete_unique_columns_central_list') { url = 'index.php?route=/database/structure/central-columns-remove'; } else if (action === 'check_tbl') { - url = 'index.php?route=/database/structure/check-table'; + url = 'index.php?route=/table/maintenance/check'; } else if (action === 'checksum_tbl') { - url = 'index.php?route=/database/structure/checksum-table'; + url = 'index.php?route=/table/maintenance/checksum'; } else if (action === 'drop_tbl') { url = 'index.php?route=/database/structure/drop-form'; } else if (action === 'empty_tbl') { @@ -314,9 +314,9 @@ AJAX.registerOnload('database/structure.js', function () { } else if (action === 'export') { url = 'index.php?route=/database/structure/export'; } else if (action === 'optimize_tbl') { - url = 'index.php?route=/database/structure/optimize-table'; + url = 'index.php?route=/table/maintenance/optimize'; } else if (action === 'repair_tbl') { - url = 'index.php?route=/database/structure/repair-table'; + url = 'index.php?route=/table/maintenance/repair'; } else if (action === 'show_create') { url = 'index.php?route=/database/structure/show-create'; } else { diff --git a/libraries/classes/Controllers/Database/QueryByExampleController.php b/libraries/classes/Controllers/Database/QueryByExampleController.php index f5b9bcd11e..9c7186d42c 100644 --- a/libraries/classes/Controllers/Database/QueryByExampleController.php +++ b/libraries/classes/Controllers/Database/QueryByExampleController.php @@ -112,7 +112,6 @@ class QueryByExampleController extends AbstractController null, // sql_query_for_bookmark null, // extra_data null, // message_to_show - null, // message null, // sql_data $goto, // goto $pmaThemeImage, // pmaThemeImage diff --git a/libraries/classes/Controllers/Database/StructureController.php b/libraries/classes/Controllers/Database/StructureController.php index c594192414..4650dc8011 100644 --- a/libraries/classes/Controllers/Database/StructureController.php +++ b/libraries/classes/Controllers/Database/StructureController.php @@ -12,7 +12,6 @@ use PhpMyAdmin\Config\PageSettings; use PhpMyAdmin\Core; use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\Html\Generator; -use PhpMyAdmin\Index; use PhpMyAdmin\Message; use PhpMyAdmin\Operations; use PhpMyAdmin\RecentFavoriteTable; @@ -1439,247 +1438,6 @@ class StructureController extends AbstractController ]); } - public function checkTable(): void - { - global $db; - - /** @var string[] $selected */ - $selected = $_POST['selected_tbl'] ?? []; - - if (empty($selected)) { - $this->response->setRequestStatus(false); - $this->response->addJSON('message', __('No table selected.')); - - return; - } - - $tables = Util::backquote($selected); - $query = 'CHECK TABLE ' . implode(', ', $tables) . ';'; - - $this->dbi->selectDb($db); - $rows = $this->dbi->fetchResult($query); - - $message = Generator::getMessage( - __('Your SQL query has been executed successfully.'), - $query, - 'success' - ); - - $indexesProblems = ''; - foreach ($selected as $table) { - $check = Index::findDuplicates($table, $db); - - if (empty($check)) { - continue; - } - - $indexesProblems .= sprintf(__('Problems with indexes of table `%s`'), $table); - $indexesProblems .= $check; - } - - $this->render('database/structure/check_table', [ - 'message' => $message, - 'rows' => $rows, - 'indexes_problems' => $indexesProblems, - ]); - } - - public function analyzeTable(): void - { - global $db, $goto, $pmaThemeImage; - - $selected = $_POST['selected_tbl'] ?? []; - - if (empty($selected)) { - $this->response->setRequestStatus(false); - $this->response->addJSON('message', __('No table selected.')); - - return; - } - - $sqlQuery = ''; - $selectedCount = count($selected); - - for ($i = 0; $i < $selectedCount; $i++) { - $sqlQuery .= (empty($sqlQuery) ? 'ANALYZE TABLE ' : ', ') . Util::backquote($selected[$i]); - } - - $sql = new Sql(); - $this->response->addHTML($sql->executeQueryAndSendQueryResponse( - null, - false, - $db, - '', - null, - null, - null, - null, - null, - null, - $goto, - $pmaThemeImage, - null, - null, - $sqlQuery, - null - )); - - if (empty($_POST['message'])) { - $_POST['message'] = Message::success(); - } - - unset($_POST['submit_mult']); - - $this->index(); - } - - public function checksumTable(): void - { - global $db, $goto, $pmaThemeImage; - - $selected = $_POST['selected_tbl'] ?? []; - - if (empty($selected)) { - $this->response->setRequestStatus(false); - $this->response->addJSON('message', __('No table selected.')); - - return; - } - - $sql_query = ''; - $selectedCount = count($selected); - - for ($i = 0; $i < $selectedCount; $i++) { - $sql_query .= (empty($sql_query) ? 'CHECKSUM TABLE ' : ', ') . Util::backquote($selected[$i]); - } - - $sql = new Sql(); - $this->response->addHTML($sql->executeQueryAndSendQueryResponse( - null, - false, - $db, - '', - null, - null, - null, - null, - null, - null, - $goto, - $pmaThemeImage, - null, - null, - $sql_query, - null - )); - - if (empty($_POST['message'])) { - $_POST['message'] = Message::success(); - } - - unset($_POST['submit_mult']); - - $this->index(); - } - - public function optimizeTable(): void - { - global $db, $goto, $pmaThemeImage; - - $selected = $_POST['selected_tbl'] ?? []; - - if (empty($selected)) { - $this->response->setRequestStatus(false); - $this->response->addJSON('message', __('No table selected.')); - - return; - } - - $sql_query = ''; - $selectedCount = count($selected); - - for ($i = 0; $i < $selectedCount; $i++) { - $sql_query .= (empty($sql_query) ? 'OPTIMIZE TABLE ' : ', ') . Util::backquote($selected[$i]); - } - - $sql = new Sql(); - $this->response->addHTML($sql->executeQueryAndSendQueryResponse( - null, - false, - $db, - '', - null, - null, - null, - null, - null, - null, - $goto, - $pmaThemeImage, - null, - null, - $sql_query, - null - )); - - if (empty($_POST['message'])) { - $_POST['message'] = Message::success(); - } - - unset($_POST['submit_mult']); - - $this->index(); - } - - public function repairTable(): void - { - global $db, $goto, $pmaThemeImage; - - $selected = $_POST['selected_tbl'] ?? []; - - if (empty($selected)) { - $this->response->setRequestStatus(false); - $this->response->addJSON('message', __('No table selected.')); - - return; - } - - $sql_query = ''; - $selectedCount = count($selected); - - for ($i = 0; $i < $selectedCount; $i++) { - $sql_query .= (empty($sql_query) ? 'REPAIR TABLE ' : ', ') . Util::backquote($selected[$i]); - } - - $sql = new Sql(); - $this->response->addHTML($sql->executeQueryAndSendQueryResponse( - null, - false, - $db, - '', - null, - null, - null, - null, - null, - null, - $goto, - $pmaThemeImage, - null, - null, - $sql_query, - null - )); - - if (empty($_POST['message'])) { - $_POST['message'] = Message::success(); - } - - unset($_POST['submit_mult']); - - $this->index(); - } - public function dropTable(): void { global $db, $message, $reload, $sql_query; diff --git a/libraries/classes/Controllers/ImportController.php b/libraries/classes/Controllers/ImportController.php index 3ffebb5519..8f7c62506f 100644 --- a/libraries/classes/Controllers/ImportController.php +++ b/libraries/classes/Controllers/ImportController.php @@ -806,7 +806,6 @@ final class ImportController extends AbstractController null, // sql_query_for_bookmark - see below null, // extra_data null, // message_to_show - null, // message null, // sql_data $goto, // goto $pmaThemeImage, // pmaThemeImage diff --git a/libraries/classes/Controllers/SqlController.php b/libraries/classes/Controllers/SqlController.php index e3ddfb63d0..f01c934a27 100644 --- a/libraries/classes/Controllers/SqlController.php +++ b/libraries/classes/Controllers/SqlController.php @@ -53,7 +53,7 @@ class SqlController extends AbstractController public function index(): void { - global $cfg, $db, $display_query, $pmaThemeImage, $sql_query, $table, $message; + global $cfg, $db, $display_query, $pmaThemeImage, $sql_query, $table; global $ajax_reload, $goto, $err_url, $find_real_end, $unlim_num_rows, $import_text, $disp_query; global $extra_data, $message_to_show, $sql_data, $disp_message, $complete_query; global $is_gotofile, $back, $table_from_sql; @@ -209,7 +209,6 @@ class SqlController extends AbstractController $import_text ?? null, $extra_data ?? null, $message_to_show ?? null, - $message ?? null, $sql_data ?? null, $goto, $pmaThemeImage, diff --git a/libraries/classes/Controllers/Table/DeleteController.php b/libraries/classes/Controllers/Table/DeleteController.php index 6d6725cfe0..f7ffc2e34f 100644 --- a/libraries/classes/Controllers/Table/DeleteController.php +++ b/libraries/classes/Controllers/Table/DeleteController.php @@ -73,7 +73,6 @@ class DeleteController extends AbstractController null, null, null, - null, $goto, $pmaThemeImage, null, diff --git a/libraries/classes/Controllers/Table/MaintenanceController.php b/libraries/classes/Controllers/Table/MaintenanceController.php new file mode 100644 index 0000000000..243a5bccd4 --- /dev/null +++ b/libraries/classes/Controllers/Table/MaintenanceController.php @@ -0,0 +1,216 @@ +model = $model; + } + + public function analyze(): void + { + global $cfg; + + /** @var string[] $selected */ + $selected = $_POST['selected_tbl'] ?? []; + + if (empty($selected) || ! is_array($selected)) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('No table selected.')); + + return; + } + + if ($cfg['DisableMultiTableMaintenance'] && count($selected) > 1) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('Maintenance operations on multiple tables are disabled.')); + + return; + } + + [$rows, $query] = $this->model->getAnalyzeTableRows($this->db, $selected); + + $message = Generator::getMessage( + __('Your SQL query has been executed successfully.'), + $query, + 'success' + ); + + $this->render('table/maintenance/analyze', [ + 'message' => $message, + 'rows' => $rows, + ]); + } + + public function check(): void + { + global $cfg; + + /** @var string[] $selected */ + $selected = $_POST['selected_tbl'] ?? []; + + if (empty($selected) || ! is_array($selected)) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('No table selected.')); + + return; + } + + if ($cfg['DisableMultiTableMaintenance'] && count($selected) > 1) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('Maintenance operations on multiple tables are disabled.')); + + return; + } + + [$rows, $query] = $this->model->getCheckTableRows($this->db, $selected); + + $message = Generator::getMessage( + __('Your SQL query has been executed successfully.'), + $query, + 'success' + ); + + $indexesProblems = $this->model->getIndexesProblems($this->db, $selected); + + $this->render('table/maintenance/check', [ + 'message' => $message, + 'rows' => $rows, + 'indexes_problems' => $indexesProblems, + ]); + } + + public function checksum(): void + { + global $cfg; + + /** @var string[] $selected */ + $selected = $_POST['selected_tbl'] ?? []; + + if (empty($selected) || ! is_array($selected)) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('No table selected.')); + + return; + } + + if ($cfg['DisableMultiTableMaintenance'] && count($selected) > 1) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('Maintenance operations on multiple tables are disabled.')); + + return; + } + + [$rows, $query, $warnings] = $this->model->getChecksumTableRows($this->db, $selected); + + $message = Generator::getMessage( + __('Your SQL query has been executed successfully.'), + $query, + 'success' + ); + + $this->render('table/maintenance/checksum', [ + 'message' => $message, + 'rows' => $rows, + 'warnings' => $warnings, + ]); + } + + public function optimize(): void + { + global $cfg; + + /** @var string[] $selected */ + $selected = $_POST['selected_tbl'] ?? []; + + if (empty($selected) || ! is_array($selected)) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('No table selected.')); + + return; + } + + if ($cfg['DisableMultiTableMaintenance'] && count($selected) > 1) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('Maintenance operations on multiple tables are disabled.')); + + return; + } + + [$rows, $query] = $this->model->getOptimizeTableRows($this->db, $selected); + + $message = Generator::getMessage( + __('Your SQL query has been executed successfully.'), + $query, + 'success' + ); + + $this->render('table/maintenance/optimize', [ + 'message' => $message, + 'rows' => $rows, + ]); + } + + public function repair(): void + { + global $cfg; + + /** @var string[] $selected */ + $selected = $_POST['selected_tbl'] ?? []; + + if (empty($selected) || ! is_array($selected)) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('No table selected.')); + + return; + } + + if ($cfg['DisableMultiTableMaintenance'] && count($selected) > 1) { + $this->response->setRequestStatus(false); + $this->response->addJSON('message', __('Maintenance operations on multiple tables are disabled.')); + + return; + } + + [$rows, $query] = $this->model->getRepairTableRows($this->db, $selected); + + $message = Generator::getMessage( + __('Your SQL query has been executed successfully.'), + $query, + 'success' + ); + + $this->render('table/maintenance/repair', [ + 'message' => $message, + 'rows' => $rows, + ]); + } +} diff --git a/libraries/classes/Controllers/Table/OperationsController.php b/libraries/classes/Controllers/Table/OperationsController.php index 559216f297..c4f0c59acc 100644 --- a/libraries/classes/Controllers/Table/OperationsController.php +++ b/libraries/classes/Controllers/Table/OperationsController.php @@ -7,7 +7,6 @@ namespace PhpMyAdmin\Controllers\Table; use PhpMyAdmin\Charsets; use PhpMyAdmin\CheckUserPrivileges; use PhpMyAdmin\Common; -use PhpMyAdmin\Controllers\SqlController; use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\Html\Generator; use PhpMyAdmin\Index; @@ -67,12 +66,11 @@ class OperationsController extends AbstractController public function index(): void { - global $containerBuilder, $url_query, $url_params, $reread_info, $tbl_is_view, $tbl_storage_engine; + global $url_query, $url_params, $reread_info, $tbl_is_view, $tbl_storage_engine; global $show_comment, $tbl_collation, $table_info_num_rows, $row_format, $auto_increment, $create_options; global $table_alters, $warning_messages, $lowerCaseNames, $db, $table, $reload, $result; global $new_tbl_storage_engine, $sql_query, $message_to_show, $columns, $hideOrderTable, $indexes; - global $notNull, $comment, $db_is_system_schema, $truncate_table_url_params, $drop_table_url_params; - global $this_sql_query; + global $notNull, $comment, $db_is_system_schema; $this->checkUserPrivileges->getPrivileges(); @@ -163,16 +161,6 @@ class OperationsController extends AbstractController return; } - /** - * If the table has to be maintained - */ - if (isset($_POST['table_maintenance'])) { - /** @var SqlController $controller */ - $controller = $containerBuilder->get(SqlController::class); - $controller->index(); - - unset($result); - } /** * Updates table comment, type and options if required */ @@ -449,8 +437,6 @@ class OperationsController extends AbstractController $hasPrivileges = $GLOBALS['table_priv'] && $GLOBALS['col_priv'] && $GLOBALS['is_reload_priv']; $switchToNew = isset($_SESSION['pma_switch_to_new']) && $_SESSION['pma_switch_to_new']; - $maintenanceActions = $this->operations->getMaintenanceActions($pma_table); - $partitions = []; $partitionsChoices = []; @@ -495,7 +481,6 @@ class OperationsController extends AbstractController 'has_foreign_keys' => $hasForeignKeys, 'has_privileges' => $hasPrivileges, 'switch_to_new' => $switchToNew, - 'maintenance_actions' => $maintenanceActions, 'is_system_schema' => isset($db_is_system_schema) && $db_is_system_schema, 'is_view' => $tbl_is_view, 'partitions' => $partitions, diff --git a/libraries/classes/Controllers/Table/SearchController.php b/libraries/classes/Controllers/Table/SearchController.php index 5bf8181527..946b610d01 100644 --- a/libraries/classes/Controllers/Table/SearchController.php +++ b/libraries/classes/Controllers/Table/SearchController.php @@ -268,7 +268,6 @@ class SearchController extends AbstractController null, // sql_query_for_bookmark null, // extra_data null, // message_to_show - null, // message null, // sql_data $GLOBALS['goto'], // goto $GLOBALS['pmaThemeImage'], // pmaThemeImage diff --git a/libraries/classes/Controllers/Table/StructureController.php b/libraries/classes/Controllers/Table/StructureController.php index b8e0ad7f00..4424deaffe 100644 --- a/libraries/classes/Controllers/Table/StructureController.php +++ b/libraries/classes/Controllers/Table/StructureController.php @@ -1068,7 +1068,6 @@ class StructureController extends AbstractController null, // sql_query_for_bookmark null, // extra_data null, // message_to_show - null, // message null, // sql_data $goto, // goto $pmaThemeImage, // pmaThemeImage diff --git a/libraries/classes/Database/MultiTableQuery.php b/libraries/classes/Database/MultiTableQuery.php index 5c343f6d20..250db54433 100644 --- a/libraries/classes/Database/MultiTableQuery.php +++ b/libraries/classes/Database/MultiTableQuery.php @@ -121,7 +121,6 @@ class MultiTableQuery null, // sql_query_for_bookmark - see below null, // extra_data null, // message_to_show - null, // message null, // sql_data $goto, // goto $pmaThemeImage, // pmaThemeImage diff --git a/libraries/classes/Operations.php b/libraries/classes/Operations.php index b5a4c3b3d0..50866b514d 100644 --- a/libraries/classes/Operations.php +++ b/libraries/classes/Operations.php @@ -12,10 +12,8 @@ use PhpMyAdmin\Plugins\Export\ExportSql; use function array_merge; use function count; use function explode; -use function htmlspecialchars; use function implode; use function mb_strtolower; -use function sprintf; use function str_replace; use function strlen; use function strtolower; @@ -595,96 +593,6 @@ class Operations return $possible_row_formats; } - /** - * @param Table $tableObject Table object - * - * @return array - */ - public function getMaintenanceActions(Table $tableObject): array - { - global $table; - - $actions = []; - - if ($tableObject->isEngine(['MYISAM', 'ARIA', 'INNODB', 'BERKELEYDB', 'TOKUDB'])) { - $actions[] = [ - 'params' => [ - 'sql_query' => 'ANALYZE TABLE ' . Util::backquote($table), - 'table_maintenance' => 'Go', - ], - 'message' => __('Analyze table'), - 'link' => 'ANALYZE_TABLE', - ]; - } - - if ($tableObject->isEngine(['MYISAM', 'ARIA', 'INNODB', 'TOKUDB'])) { - $actions[] = [ - 'params' => [ - 'sql_query' => 'CHECK TABLE ' . Util::backquote($table), - 'table_maintenance' => 'Go', - ], - 'message' => __('Check table'), - 'link' => 'CHECK_TABLE', - ]; - } - - $actions[] = [ - 'params' => [ - 'sql_query' => 'CHECKSUM TABLE ' . Util::backquote($table), - 'table_maintenance' => 'Go', - ], - 'message' => __('Checksum table'), - 'link' => 'CHECKSUM_TABLE', - ]; - - if ($tableObject->isEngine(['INNODB'])) { - $actions[] = [ - 'params' => [ - 'sql_query' => 'ALTER TABLE ' . Util::backquote($table) . ' ENGINE = InnoDB;', - ], - 'message' => __('Defragment table'), - 'link' => 'InnoDB_File_Defragmenting', - ]; - } - - $actions[] = [ - 'params' => [ - 'sql_query' => 'FLUSH TABLE ' . Util::backquote($table), - 'message_to_show' => sprintf( - __('Table %s has been flushed.'), - htmlspecialchars($table) - ), - 'reload' => true, - ], - 'message' => __('Flush the table (FLUSH)'), - 'link' => 'FLUSH', - ]; - - if ($tableObject->isEngine(['MYISAM', 'ARIA', 'INNODB', 'BERKELEYDB', 'TOKUDB'])) { - $actions[] = [ - 'params' => [ - 'sql_query' => 'OPTIMIZE TABLE ' . Util::backquote($table), - 'table_maintenance' => 'Go', - ], - 'message' => __('Optimize table'), - 'link' => 'OPTIMIZE_TABLE', - ]; - } - - if ($tableObject->isEngine(['MYISAM', 'ARIA'])) { - $actions[] = [ - 'params' => [ - 'sql_query' => 'REPAIR TABLE ' . Util::backquote($table), - 'table_maintenance' => 'Go', - ], - 'message' => __('Repair table'), - 'link' => 'REPAIR_TABLE', - ]; - } - - return $actions; - } - /** * @return array */ diff --git a/libraries/classes/Sql.php b/libraries/classes/Sql.php index 0837e5a065..21c3eb619a 100644 --- a/libraries/classes/Sql.php +++ b/libraries/classes/Sql.php @@ -26,7 +26,6 @@ use function htmlspecialchars; use function in_array; use function is_array; use function is_bool; -use function is_string; use function microtime; use function session_start; use function session_write_close; @@ -1479,7 +1478,6 @@ class Sql * @param array $analyzed_sql_results analysed sql results * @param string $db current database * @param string $table current table - * @param Message|string|null $message message to show * @param array|null $sql_data sql data * @param DisplayResults $displayResultsObject Instance of DisplayResults * @param string $pmaThemeImage uri of the theme image @@ -1498,7 +1496,6 @@ class Sql array $analyzed_sql_results, $db, $table, - $message, ?array $sql_data, $displayResultsObject, $pmaThemeImage, @@ -1606,36 +1603,6 @@ class Sql ]; } - $tableMaintenanceHtml = ''; - if (isset($_POST['table_maintenance'])) { - $scripts->addFile('makegrid.js'); - $scripts->addFile('sql.js'); - if (isset($message)) { - $message = is_string($message) ? Message::success($message) : $message; - $tableMaintenanceHtml = Generator::getMessage( - $message, - $GLOBALS['sql_query'], - 'success' - ); - } - $tableMaintenanceHtml .= $this->getHtmlForSqlQueryResultsTable( - $displayResultsObject, - $pmaThemeImage, - $url_query, - $displayParts, - false, - $unlim_num_rows, - $num_rows, - $showtable, - $result, - $analyzed_sql_results - ); - if (empty($sql_data) || ($sql_data['valid_queries'] <= 1)) { - $response->addHTML($tableMaintenanceHtml); - exit; - } - } - if (! isset($_POST['printview']) || $_POST['printview'] != '1') { $scripts->addFile('makegrid.js'); $scripts->addFile('sql.js'); @@ -1704,7 +1671,6 @@ class Sql } return $this->template->render('sql/sql_query_results', [ - 'table_maintenance' => $tableMaintenanceHtml, 'previous_update_query' => $previousUpdateQueryHtml, 'profiling_chart' => $profilingChartHtml, 'missing_unique_column_message' => $missingUniqueColumnMessage, @@ -1725,7 +1691,6 @@ class Sql * @param string|null $sql_query_for_bookmark the sql query to be stored as bookmark * @param array|null $extra_data extra data * @param string|null $message_to_show message to show - * @param Message|string|null $message message * @param array|null $sql_data sql data * @param string $goto goto page url * @param string $pmaThemeImage uri of the PMA theme image @@ -1743,7 +1708,6 @@ class Sql $sql_query_for_bookmark, $extra_data, $message_to_show, - $message, $sql_data, $goto, $pmaThemeImage, @@ -1774,7 +1738,6 @@ class Sql $sql_query_for_bookmark, // sql_query_for_bookmark $extra_data, // extra_data $message_to_show, // message_to_show - $message, // message $sql_data, // sql_data $goto, // goto $pmaThemeImage, // pmaThemeImage @@ -1796,7 +1759,6 @@ class Sql * @param string|null $sql_query_for_bookmark the sql query to be stored as bookmark * @param array|null $extra_data extra data * @param string|null $message_to_show message to show - * @param Message|string|null $message message * @param array|null $sql_data sql data * @param string $goto goto page url * @param string $pmaThemeImage uri of the PMA theme image @@ -1816,7 +1778,6 @@ class Sql ?string $sql_query_for_bookmark, $extra_data, ?string $message_to_show, - $message, $sql_data, $goto, $pmaThemeImage, @@ -1913,7 +1874,6 @@ class Sql $analyzed_sql_results, $db, $table, - $message ?? null, $sql_data ?? null, $displayResultsObject, $pmaThemeImage, diff --git a/libraries/classes/Table/Maintenance.php b/libraries/classes/Table/Maintenance.php new file mode 100644 index 0000000000..9ed72ef0c3 --- /dev/null +++ b/libraries/classes/Table/Maintenance.php @@ -0,0 +1,142 @@ +dbi = $dbi; + } + + /** + * @param string[] $tables + * + * @return array + */ + public function getAnalyzeTableRows(string $db, array $tables): array + { + $backQuotedTables = Util::backquote($tables); + $query = 'ANALYZE TABLE ' . implode(', ', $backQuotedTables) . ';'; + + $this->dbi->selectDb($db); + $result = $this->dbi->fetchResult($query); + + $rows = []; + foreach ($result as $row) { + $rows[$row['Table']][] = $row; + } + + return [$rows, $query]; + } + + /** + * @param string[] $tables + * + * @return array + */ + public function getCheckTableRows(string $db, array $tables): array + { + $backQuotedTables = Util::backquote($tables); + $query = 'CHECK TABLE ' . implode(', ', $backQuotedTables) . ';'; + + $this->dbi->selectDb($db); + $result = $this->dbi->fetchResult($query); + + $rows = []; + foreach ($result as $row) { + $rows[$row['Table']][] = $row; + } + + return [$rows, $query]; + } + + /** + * @param string[] $tables + * + * @return array + */ + public function getChecksumTableRows(string $db, array $tables): array + { + $backQuotedTables = Util::backquote($tables); + $query = 'CHECKSUM TABLE ' . implode(', ', $backQuotedTables) . ';'; + + $this->dbi->selectDb($db); + $rows = $this->dbi->fetchResult($query); + $warnings = $this->dbi->getWarnings(); + + return [$rows, $query, $warnings]; + } + + /** @param string[] $tables */ + public function getIndexesProblems(string $db, array $tables): string + { + $indexesProblems = ''; + + foreach ($tables as $table) { + $check = Index::findDuplicates($table, $db); + + if (empty($check)) { + continue; + } + + $indexesProblems .= sprintf(__('Problems with indexes of table `%s`'), $table); + $indexesProblems .= $check; + } + + return $indexesProblems; + } + + /** + * @param string[] $tables + * + * @return array + */ + public function getOptimizeTableRows(string $db, array $tables): array + { + $backQuotedTables = Util::backquote($tables); + $query = 'OPTIMIZE TABLE ' . implode(', ', $backQuotedTables) . ';'; + + $this->dbi->selectDb($db); + $result = $this->dbi->fetchResult($query); + + $rows = []; + foreach ($result as $row) { + $rows[$row['Table']][] = $row; + } + + return [$rows, $query]; + } + + /** + * @param string[] $tables + * + * @return array + */ + public function getRepairTableRows(string $db, array $tables): array + { + $backQuotedTables = Util::backquote($tables); + $query = 'REPAIR TABLE ' . implode(', ', $backQuotedTables) . ';'; + + $this->dbi->selectDb($db); + $result = $this->dbi->fetchResult($query); + + $rows = []; + foreach ($result as $row) { + $rows[$row['Table']][] = $row; + } + + return [$rows, $query]; + } +} diff --git a/libraries/routes.php b/libraries/routes.php index a4c72c98e8..4683d105b9 100644 --- a/libraries/routes.php +++ b/libraries/routes.php @@ -76,6 +76,7 @@ use PhpMyAdmin\Controllers\Table\GetFieldController; use PhpMyAdmin\Controllers\Table\GisVisualizationController; use PhpMyAdmin\Controllers\Table\ImportController as TableImportController; use PhpMyAdmin\Controllers\Table\IndexesController; +use PhpMyAdmin\Controllers\Table\MaintenanceController; use PhpMyAdmin\Controllers\Table\OperationsController as TableOperationsController; use PhpMyAdmin\Controllers\Table\RecentFavoriteController; use PhpMyAdmin\Controllers\Table\RelationController; @@ -141,7 +142,6 @@ return static function (RouteCollector $routes): void { $routes->addRoute(['GET', 'POST'], '', [StructureController::class, 'index']); $routes->post('/add-prefix', [StructureController::class, 'addPrefix']); $routes->post('/add-prefix-table', [StructureController::class, 'addPrefixTable']); - $routes->post('/analyze-table', [StructureController::class, 'analyzeTable']); $routes->post('/central-columns-add', [StructureController::class, 'centralColumnsAdd']); $routes->post('/central-columns-make-consistent', [ StructureController::class, @@ -149,8 +149,6 @@ return static function (RouteCollector $routes): void { ]); $routes->post('/central-columns-remove', [StructureController::class, 'centralColumnsRemove']); $routes->post('/change-prefix-form', [StructureController::class, 'changePrefixForm']); - $routes->post('/check-table', [StructureController::class, 'checkTable']); - $routes->post('/checksum-table', [StructureController::class, 'checksumTable']); $routes->post('/copy-form', [StructureController::class, 'copyForm']); $routes->post('/copy-table', [StructureController::class, 'copyTable']); $routes->post('/copy-table-with-prefix', [StructureController::class, 'copyTableWithPrefix']); @@ -163,12 +161,10 @@ return static function (RouteCollector $routes): void { StructureController::class, 'addRemoveFavoriteTablesAction', ]); - $routes->post('/optimize-table', [StructureController::class, 'optimizeTable']); $routes->addRoute(['GET', 'POST'], '/real-row-count', [ StructureController::class, 'handleRealRowCountRequestAction', ]); - $routes->post('/repair-table', [StructureController::class, 'repairTable']); $routes->post('/replace-prefix', [StructureController::class, 'replacePrefix']); $routes->post('/show-create', [StructureController::class, 'showCreate']); }); @@ -278,6 +274,13 @@ return static function (RouteCollector $routes): void { $routes->addRoute(['GET', 'POST'], '/gis-visualization', [GisVisualizationController::class, 'index']); $routes->addRoute(['GET', 'POST'], '/import', [TableImportController::class, 'index']); $routes->addRoute(['GET', 'POST'], '/indexes', [IndexesController::class, 'index']); + $routes->addGroup('/maintenance', static function (RouteCollector $routes): void { + $routes->post('/analyze', [MaintenanceController::class, 'analyze']); + $routes->post('/check', [MaintenanceController::class, 'check']); + $routes->post('/checksum', [MaintenanceController::class, 'checksum']); + $routes->post('/optimize', [MaintenanceController::class, 'optimize']); + $routes->post('/repair', [MaintenanceController::class, 'repair']); + }); $routes->addRoute(['GET', 'POST'], '/operations', [TableOperationsController::class, 'index']); $routes->addRoute(['GET', 'POST'], '/recent-favorite', [RecentFavoriteController::class, 'index']); $routes->addRoute(['GET', 'POST'], '/relation', [RelationController::class, 'index']); diff --git a/libraries/services.php b/libraries/services.php index 9ef0bae368..ad56471d1a 100644 --- a/libraries/services.php +++ b/libraries/services.php @@ -171,6 +171,10 @@ return [ 'class' => PhpMyAdmin\Server\Status\Monitor::class, 'arguments' => ['@dbi'], ], + 'table_maintenance' => [ + 'class' => PhpMyAdmin\Table\Maintenance::class, + 'arguments' => ['dbi' => '@dbi'], + ], 'table_search' => [ 'class' => PhpMyAdmin\Table\Search::class, 'arguments' => ['dbi' => '@dbi'], diff --git a/libraries/services_controllers.php b/libraries/services_controllers.php index 972d0aaae1..023f2a29f3 100644 --- a/libraries/services_controllers.php +++ b/libraries/services_controllers.php @@ -710,6 +710,17 @@ return [ 'table' => '%table%', ], ], + PhpMyAdmin\Controllers\Table\MaintenanceController::class => [ + 'class' => PhpMyAdmin\Controllers\Table\MaintenanceController::class, + 'arguments' => [ + 'response' => '@response', + 'dbi' => '@dbi', + 'template' => '@template', + 'db' => '%db%', + 'table' => '%table%', + 'model' => '@table_maintenance', + ], + ], PhpMyAdmin\Controllers\Table\OperationsController::class => [ 'class' => PhpMyAdmin\Controllers\Table\OperationsController::class, 'arguments' => [ diff --git a/templates/database/structure/check_table.twig b/templates/database/structure/check_table.twig deleted file mode 100644 index e3e7a415eb..0000000000 --- a/templates/database/structure/check_table.twig +++ /dev/null @@ -1,29 +0,0 @@ -
-

- {% trans 'Checking tables' %} - {{ show_mysql_docu('CHECK_TABLE') }} -

- - {{ message|raw }} - - - - - - - - - - - {% for row in rows %} - - - - - - {% endfor %} - -
{% trans 'Table' %}{% trans 'Message type' %}{% trans 'Message' %}
{{ row.Table }}{{ row.Msg_type|title }}{{ row.Msg_text }}
- - {{ indexes_problems|raw }} -
diff --git a/templates/sql/sql_query_results.twig b/templates/sql/sql_query_results.twig index f3ebfd93b1..36c10e1af9 100644 --- a/templates/sql/sql_query_results.twig +++ b/templates/sql/sql_query_results.twig @@ -1,4 +1,3 @@ -{{ table_maintenance|raw }}
{{ previous_update_query|raw }} {{ profiling_chart|raw }} diff --git a/templates/table/maintenance/analyze.twig b/templates/table/maintenance/analyze.twig new file mode 100644 index 0000000000..1ea2822120 --- /dev/null +++ b/templates/table/maintenance/analyze.twig @@ -0,0 +1,39 @@ +
+

+ {% trans 'Analyze table' %} + {{ show_mysql_docu('ANALYZE_TABLE') }} +

+ + {{ message|raw }} + + {% for name, table in rows %} +
+
{{ name }}
+ +
    + {% for row in table %} +
  • + {% if row.Op|lower != 'analyze' %} + {{ row.Op|title }} + {% endif %} + + {% set badge_variation %} + {%- if row.Msg_type|lower == 'error' -%} + badge-danger + {%- elseif row.Msg_type|lower == 'warning' -%} + badge-warning + {%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%} + badge-info + {%- else -%} + badge-secondary + {%- endif -%} + {% endset %} + {{ row.Msg_type|title }} + + {{ row.Msg_text }} +
  • + {% endfor %} +
+
+ {% endfor %} +
diff --git a/templates/table/maintenance/check.twig b/templates/table/maintenance/check.twig new file mode 100644 index 0000000000..bededab6b0 --- /dev/null +++ b/templates/table/maintenance/check.twig @@ -0,0 +1,41 @@ +
+

+ {% trans 'Check table' %} + {{ show_mysql_docu('CHECK_TABLE') }} +

+ + {{ message|raw }} + + {% for name, table in rows %} +
+
{{ name }}
+ +
    + {% for row in table %} +
  • + {% if row.Op|lower != 'check' %} + {{ row.Op|title }} + {% endif %} + + {% set badge_variation %} + {%- if row.Msg_type|lower == 'error' -%} + badge-danger + {%- elseif row.Msg_type|lower == 'warning' -%} + badge-warning + {%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%} + badge-info + {%- else -%} + badge-secondary + {%- endif -%} + {% endset %} + {{ row.Msg_type|title }} + + {{ row.Msg_text }} +
  • + {% endfor %} +
+
+ {% endfor %} + + {{ indexes_problems|raw }} +
diff --git a/templates/table/maintenance/checksum.twig b/templates/table/maintenance/checksum.twig new file mode 100644 index 0000000000..7eb3a45574 --- /dev/null +++ b/templates/table/maintenance/checksum.twig @@ -0,0 +1,37 @@ +
+

+ {% trans 'Checksum table' %} + {{ show_mysql_docu('CHECKSUM_TABLE') }} +

+ + {{ message|raw }} + + + + + + + + + + {% for row in rows %} + + + + + {% endfor %} + +
{% trans 'Table' %}{% trans 'Checksum' %}
{{ row.Table }} + {% if row.Checksum is not null %} + {{ row.Checksum }} + {% else %} + NULL + {% endif %} +
+ + {% for warning in warnings %} + {% apply notice %} + {{ warning.Level }}: #{{ warning.Code }} {{ warning.Message }} + {% endapply %} + {% endfor %} +
diff --git a/templates/table/maintenance/optimize.twig b/templates/table/maintenance/optimize.twig new file mode 100644 index 0000000000..fe5fe761e7 --- /dev/null +++ b/templates/table/maintenance/optimize.twig @@ -0,0 +1,39 @@ +
+

+ {% trans 'Optimize table' %} + {{ show_mysql_docu('OPTIMIZE_TABLE') }} +

+ + {{ message|raw }} + + {% for name, table in rows %} +
+
{{ name }}
+ +
    + {% for row in table %} +
  • + {% if row.Op|lower != 'optimize' %} + {{ row.Op|title }} + {% endif %} + + {% set badge_variation %} + {%- if row.Msg_type|lower == 'error' -%} + badge-danger + {%- elseif row.Msg_type|lower == 'warning' -%} + badge-warning + {%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%} + badge-info + {%- else -%} + badge-secondary + {%- endif -%} + {% endset %} + {{ row.Msg_type|title }} + + {{ row.Msg_text }} +
  • + {% endfor %} +
+
+ {% endfor %} +
diff --git a/templates/table/maintenance/repair.twig b/templates/table/maintenance/repair.twig new file mode 100644 index 0000000000..a9cf08e430 --- /dev/null +++ b/templates/table/maintenance/repair.twig @@ -0,0 +1,39 @@ +
+

+ {% trans 'Repair table' %} + {{ show_mysql_docu('REPAIR_TABLE') }} +

+ + {{ message|raw }} + + {% for name, table in rows %} +
+
{{ name }}
+ +
    + {% for row in table %} +
  • + {% if row.Op|lower != 'repair' %} + {{ row.Op|title }} + {% endif %} + + {% set badge_variation %} + {%- if row.Msg_type|lower == 'error' -%} + badge-danger + {%- elseif row.Msg_type|lower == 'warning' -%} + badge-warning + {%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%} + badge-info + {%- else -%} + badge-secondary + {%- endif -%} + {% endset %} + {{ row.Msg_type|title }} + + {{ row.Msg_text }} +
  • + {% endfor %} +
+
+ {% endfor %} +
diff --git a/templates/table/operations/index.twig b/templates/table/operations/index.twig index 6b64a3c7a1..6b206b00b2 100644 --- a/templates/table/operations/index.twig +++ b/templates/table/operations/index.twig @@ -311,16 +311,68 @@
{% trans 'Table maintenance' %}
diff --git a/themes/bootstrap/scss/_bootstrap.scss b/themes/bootstrap/scss/_bootstrap.scss index e1f54c264f..3ad3a8faa1 100644 --- a/themes/bootstrap/scss/_bootstrap.scss +++ b/themes/bootstrap/scss/_bootstrap.scss @@ -20,7 +20,7 @@ @import "../../../node_modules/bootstrap/scss/card"; @import "../../../node_modules/bootstrap/scss/breadcrumb"; //@import "../../../node_modules/bootstrap/scss/pagination"; -//@import "../../../node_modules/bootstrap/scss/badge"; +@import "../../../node_modules/bootstrap/scss/badge"; //@import "../../../node_modules/bootstrap/scss/jumbotron"; @import "../../../node_modules/bootstrap/scss/alert"; //@import "../../../node_modules/bootstrap/scss/progress";