diff --git a/db_structure.php b/db_structure.php index 543bade533..7eb804b005 100644 --- a/db_structure.php +++ b/db_structure.php @@ -55,6 +55,13 @@ $url_query .= '&goto=db_structure.php'; $sub_part = '_structure'; require 'libraries/db_info.inc.php'; +// If there is an Ajax request for real row count of a table. +if ($GLOBALS['is_ajax_request'] && isset($_REQUEST['real_row_count']) + && $_REQUEST['real_row_count'] == true) { + PMA_handleRealRowCountRequest(); + exit; +} + if (!PMA_DRIZZLE) { include_once 'libraries/replication.inc.php'; } else { @@ -278,7 +285,7 @@ foreach ($tables as $keyname => $current_table) { } } // Handle favorite table list. ----ENDS---- - list($html_output, $odd_row) = PMA_getHtmlForStructureTableRow( + list($html_output, $odd_row, $approx_rows) = PMA_getHtmlForStructureTableRow( $i, $odd_row, $table_is_view, $current_table, $browse_table_label, $tracking_icon, $server_slave_status, $browse_table, $tbl_url_query, $search_table, $db_is_system_schema, @@ -299,7 +306,7 @@ $response->addHTML( PMA_getHtmlBodyForTableSummary( $num_tables, $server_slave_status, $db_is_system_schema, $sum_entries, $db_collation, $is_show_stats, $sum_size, $overhead_size, $create_time_all, - $update_time_all, $check_time_all + $update_time_all, $check_time_all, $approx_rows ) ); $response->addHTML(''); diff --git a/doc/faq.rst b/doc/faq.rst index 243ddfe1f4..78e33524c5 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -940,6 +940,9 @@ phpMyAdmin uses a quick method to get the row count, and this method only returns an approximate count in the case of InnoDB tables. See :config:option:`$cfg['MaxExactCount']` for a way to modify those results, but this could have a serious impact on performance. +However, one can easily replace the approximate row count with exact count by +simply clicking on the approximate count. This can also be done for all tables +at once by clicking on the rows sum displayed at the bottom. .. _faq3_12: diff --git a/js/db_structure.js b/js/db_structure.js index 56c4391e7c..0e53d61b43 100644 --- a/js/db_structure.js +++ b/js/db_structure.js @@ -29,6 +29,8 @@ AJAX.registerTeardown('db_structure.js', function () { $('a.drop_tracking_anchor.ajax').die('click'); $('#real_end_input').die('click'); $("a.favorite_table_anchor.ajax").die('click'); + $('a.real_row_count').off('click'); + $('a.row_count_sum').off('click'); }); /** @@ -126,11 +128,50 @@ function PMA_adjustTotals() { // Update summary with new data var $summary = $("#tbl_summary_row"); $summary.find('.tbl_num').text($.sprintf(PMA_messages.strTables, tableSum)); - $summary.find('.tbl_rows').text(strRowSum); + $summary.find('.row_count_sum').text(strRowSum); $summary.find('.tbl_size').text(sizeSum + " " + byteUnits[size_magnitude]); $summary.find('.tbl_overhead').text(overheadSum + " " + byteUnits[overhead_magnitude]); } +/** + * Gets the real row count for a table or DB. + * @param object $target Target for appending the real count value. + */ +function PMA_fetchRealRowCount($target) +{ + $.ajax({ + type: 'GET', + url: $target.attr('href'), + cache: false, + dataType: 'json', + success: function (response) { + if (response.success) { + // If to update all row counts for a DB. + if (response.real_row_count_all) { + $.each(JSON.parse(response.real_row_count_all), + function (index, table) { + // Update each table row count. + $('table.data td[data-table*="' + table.table + '"]') + .text(table.row_count); + }); + } + // If to update a particular table's row count. + if (response.real_row_count) { + // Append the parent cell with real row count. + $target.parent().text(response.real_row_count); + } + // Adjust the 'Sum' displayed at the bottom. + PMA_adjustTotals(); + } else { + PMA_ajaxShowMessage(PMA_messages.strErrorRealRowCount); + } + }, + error: function () { + PMA_ajaxShowMessage(PMA_messages.strErrorRealRowCount); + } + }); +} + AJAX.registerOnload('db_structure.js', function () { /** * Handler for the print view multisubmit. @@ -396,4 +437,15 @@ AJAX.registerOnload('db_structure.js', function () { $(this).attr("title") ); }); + + // Get real row count via Ajax. + $('a.real_row_count').on('click', function (event) { + event.preventDefault(); + PMA_fetchRealRowCount($(this)); + }); + // Get all real row count. + $('a.row_count_sum').on('click', function (event) { + event.preventDefault(); + PMA_fetchRealRowCount($(this)); + }); }); // end $() diff --git a/js/messages.php b/js/messages.php index de12846715..3f26cdbed1 100644 --- a/js/messages.php +++ b/js/messages.php @@ -246,6 +246,7 @@ $js_messages['strNo'] = __('No'); $js_messages['strForeignKeyCheck'] = __('Foreign key check:'); $js_messages['strForeignKeyCheckEnabled'] = __('(Enabled)'); $js_messages['strForeignKeyCheckDisabled'] = __('(Disabled)'); +$js_messages['strErrorRealRowCount'] = __('Failed to get real row count.'); /* For db_search.js */ $js_messages['strSearching'] = __('Searching'); diff --git a/libraries/structure.lib.php b/libraries/structure.lib.php index 5900c49573..1c2d992590 100644 --- a/libraries/structure.lib.php +++ b/libraries/structure.lib.php @@ -152,13 +152,14 @@ function PMA_getTableDropQueryAndMessage($table_is_view, $current_table) * @param string $create_time_all create time * @param string $update_time_all update time * @param string $check_time_all check time + * @param boolean $approx_rows whether any table has approx row count or not * * @return string $html_output */ function PMA_getHtmlBodyForTableSummary($num_tables, $server_slave_status, $db_is_system_schema, $sum_entries, $db_collation, $is_show_stats, $sum_size, $overhead_size, $create_time_all, $update_time_all, - $check_time_all + $check_time_all, $approx_rows ) { $html_output = '' . ''; @@ -175,8 +176,21 @@ function PMA_getHtmlBodyForTableSummary($num_tables, $server_slave_status, $html_output .= '' . __('Sum') . ''; + + $row_count_sum = PMA_Util::formatNumber($sum_entries, 0); + // If a table shows approximate rows count, display update-all-real-count anchor. + if (isset($approx_rows)) { + $row_sum_url['ajax_request'] = true; + $row_sum_url['db'] = $GLOBALS['db']; + $row_sum_url['real_row_count'] = 'true'; + $row_sum_url['real_row_count_all'] = 'true'; + } + $cell_text = ($approx_rows) + ? '' . '~' . $row_count_sum . '' + : $row_count_sum; $html_output .= '' - . PMA_Util::formatNumber($sum_entries, 0) + . $cell_text . ''; if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)) { @@ -440,7 +454,7 @@ function PMA_getTimeForCreateUpdateCheck($current_table, $time_label, $time_all) * @param boolean $do do * @param integer $colspan_for_structure colspan for structure * - * @return array $html_output, $odd_row + * @return array $html_output, $odd_row, $approx_rows */ function PMA_getHtmlForStructureTableRow( $curr, $odd_row, $table_is_view, $current_table, @@ -503,11 +517,12 @@ function PMA_getHtmlForStructureTableRow( && ($current_table['ENGINE'] != null || $table_is_view) ) { - $html_output .= PMA_getHtmlForNotNullEngineViewTable( + list($html_view_table, $approx_rows) = PMA_getHtmlForNotNullEngineViewTable ( $table_is_view, $current_table, $collation, $is_show_stats, $tbl_url_query, $formatted_size, $unit, $overhead, $create_time, $update_time, $check_time ); + $html_output .= $html_view_table; } elseif ($table_is_view) { $html_output .= PMA_getHtmlForViewTable($is_show_stats); } else { @@ -518,7 +533,7 @@ function PMA_getHtmlForStructureTableRow( } // end if (isset($current_table['TABLE_ROWS'])) else $html_output .= ''; - return array($html_output, $odd_row); + return array($html_output, $odd_row, $approx_rows); } /** @@ -668,11 +683,29 @@ function PMA_getHtmlForNotNullEngineViewTable($table_is_view, $current_table, $show_superscript = ''; } - $html_output .= '' - . $row_count_pre . PMA_Util::formatNumber( - $current_table['TABLE_ROWS'], 0 - ) - . $show_superscript . ''; + // Set a flag if there are approximate row counts on page. + if (! empty($row_count_pre)) { + $approx_rows = true; + } + // Get the row count. + $row_count = $row_count_pre + . PMA_Util::formatNumber($current_table['TABLE_ROWS'], 0); + // URL parameters to fetch the real row count. + $real_count_url['ajax_request'] = true; + $real_count_url['db'] = $GLOBALS['db']; + $real_count_url['table'] = $current_table['TABLE_NAME']; + $real_count_url['real_row_count'] = 'true'; + // Content to be appended into 'tbl_rows' cell. + // If row count is approximate, display it as an anchor to get real count. + $cell_text = (! empty($row_count_pre)) + ? '' . $row_count . '' + : $row_count; + $html_output .= '' + . $cell_text + . $show_superscript + . ''; if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)) { $html_output .= '' @@ -693,7 +726,7 @@ function PMA_getHtmlForNotNullEngineViewTable($table_is_view, $current_table, $create_time, $update_time, $check_time ); - return $html_output; + return array($html_output, $approx_rows); } /** @@ -770,7 +803,8 @@ function PMA_tableHeader($db_is_system_schema = false, $replication = false) . '' . PMA_sortableTableHeader(__('Rows'), 'records', 'DESC') . PMA_Util::showHint( PMA_sanitize( - __('May be approximate. See [doc@faq3-11]FAQ 3.11[/doc].') + __('May be approximate. Click on the number to get the exact count.' + . ' See [doc@faq3-11]FAQ 3.11[/doc].') ) ) . "\n" . '' . "\n"; @@ -2972,4 +3006,71 @@ function PMA_getShowCreate($db, $db_object, $type = 'table') return $result; } + +/** + * Returns the real row count for a table + * @param string $db Database name + * @param string $table Table name + * + * @return number + */ +function PMA_getRealRowCountTable($db, $table) +{ + // SQL query to get row count for a table. + $sql_query = 'SELECT COUNT(*) AS ' . PMA_Util::backquote('row_count') + . ' FROM ' . PMA_Util::backquote($db) . '.' + . PMA_Util::backquote($table); + $result = $GLOBALS['dbi']->fetchSingleRow($sql_query); + $row_count = $result['row_count']; + + return $row_count; +} + +/** + * Returns the real row count for all tables of a DB + * @param string $db Database name + * @param array $tables Array containing table names. + * + * @return array + */ +function PMA_getRealRowCountDb($db, $tables) +{ + // Array to store the results. + $row_count_all = array(); + // Iterate over each table and fetch real row count. + foreach ($tables as $key => $table) { + $row_count = PMA_getRealRowCountTable($db, $table['TABLE_NAME']); + array_push( + $row_count_all, + array('table' => $table['TABLE_NAME'], 'row_count' => $row_count) + ); + } + + return $row_count_all; +} + +/** + * Handles request for real row count on database level view page. + */ +function PMA_handleRealRowCountRequest() +{ + $ajax_response = PMA_Response::getInstance(); + // If there is a request to update all table's row count. + if (isset($_REQUEST['real_row_count_all'])) { + $real_row_count_all = PMA_getRealRowCountDb($GLOBALS['db'], + $GLOBALS['tables']); + $ajax_response->addJSON( + 'real_row_count_all', + json_encode($real_row_count_all) + ); + return true; + } + // Get the real row count for the table. + $real_row_count = PMA_getRealRowCountTable($GLOBALS['db'], + $_REQUEST['table']); + // Format the number. + $real_row_count = PMA_Util::formatNumber($real_row_count, 0); + $ajax_response->addJSON('real_row_count', $real_row_count); + return true; +} ?>