patch #2356575 [display] Sortable database columns
This commit is contained in:
@@ -14,6 +14,8 @@ $HeadURL: https://phpmyadmin.svn.sourceforge.net/svnroot/phpmyadmin/trunk/phpMyA
|
|||||||
+ rfe #1821619 LeftFrameDBSeparator can be an array
|
+ rfe #1821619 LeftFrameDBSeparator can be an array
|
||||||
+ patch #1821619 [privileges] Extra back reference when editing table-specific
|
+ patch #1821619 [privileges] Extra back reference when editing table-specific
|
||||||
privileges, thanks to Herman van Rink - helmo
|
privileges, thanks to Herman van Rink - helmo
|
||||||
|
+ patch #2356575 [display] Sortable database columns,
|
||||||
|
thanks to Bryce Thornton - brycethornton
|
||||||
|
|
||||||
3.1.2.0 (not yet released)
|
3.1.2.0 (not yet released)
|
||||||
- bug #1253252 [display] Can't NULL a column with relation defined
|
- bug #1253252 [display] Can't NULL a column with relation defined
|
||||||
|
@@ -77,6 +77,7 @@ $db_collation = PMA_getDbCollation($db);
|
|||||||
* @uses $GLOBALS['strSize']
|
* @uses $GLOBALS['strSize']
|
||||||
* @uses $GLOBALS['strOverhead']
|
* @uses $GLOBALS['strOverhead']
|
||||||
* @uses $GLOBALS['structure_tbl_col_cnt']
|
* @uses $GLOBALS['structure_tbl_col_cnt']
|
||||||
|
* @uses PMA_SortableTableHeader()
|
||||||
* @param boolean $db_is_information_schema
|
* @param boolean $db_is_information_schema
|
||||||
*/
|
*/
|
||||||
function PMA_TableHeader($db_is_information_schema = false)
|
function PMA_TableHeader($db_is_information_schema = false)
|
||||||
@@ -92,22 +93,22 @@ function PMA_TableHeader($db_is_information_schema = false)
|
|||||||
echo '<table class="data" style="float: left;">' . "\n"
|
echo '<table class="data" style="float: left;">' . "\n"
|
||||||
.'<thead>' . "\n"
|
.'<thead>' . "\n"
|
||||||
.'<tr><td></td>' . "\n"
|
.'<tr><td></td>' . "\n"
|
||||||
.' <th>' . $GLOBALS['strTable'] . '</th>' . "\n"
|
.' <th>' . PMA_SortableTableHeader($GLOBALS['strTable'], 'table') . '</th>' . "\n"
|
||||||
.' <th colspan="' . $action_colspan . '">' . "\n"
|
.' <th colspan="' . $action_colspan . '">' . "\n"
|
||||||
.' ' . $GLOBALS['strAction'] . "\n"
|
.' ' . $GLOBALS['strAction'] . "\n"
|
||||||
.' </th>'
|
.' </th>'
|
||||||
.' <th>' . $GLOBALS['strRecords']
|
.' <th>' . PMA_SortableTableHeader($GLOBALS['strRecords'], 'records')
|
||||||
.PMA_showHint(PMA_sanitize($GLOBALS['strApproximateCount'])) . "\n"
|
.PMA_showHint(PMA_sanitize($GLOBALS['strApproximateCount'])) . "\n"
|
||||||
.' </th>' . "\n";
|
.' </th>' . "\n";
|
||||||
if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)) {
|
if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)) {
|
||||||
echo ' <th>' . $GLOBALS['strType'] . '</th>' . "\n";
|
echo ' <th>' . PMA_SortableTableHeader($GLOBALS['strType'], 'type') . '</th>' . "\n";
|
||||||
$cnt++;
|
$cnt++;
|
||||||
echo ' <th>' . $GLOBALS['strCollation'] . '</th>' . "\n";
|
echo ' <th>' . PMA_SortableTableHeader($GLOBALS['strCollation'], 'collation') . '</th>' . "\n";
|
||||||
$cnt++;
|
$cnt++;
|
||||||
}
|
}
|
||||||
if ($GLOBALS['is_show_stats']) {
|
if ($GLOBALS['is_show_stats']) {
|
||||||
echo ' <th>' . $GLOBALS['strSize'] . '</th>' . "\n"
|
echo ' <th>' . PMA_SortableTableHeader($GLOBALS['strSize'], 'size') . '</th>' . "\n"
|
||||||
. ' <th>' . $GLOBALS['strOverhead'] . '</th>' . "\n";
|
. ' <th>' . PMA_SortableTableHeader($GLOBALS['strOverhead'], 'overhead') . '</th>' . "\n";
|
||||||
$cnt += 2;
|
$cnt += 2;
|
||||||
}
|
}
|
||||||
echo '</tr>' . "\n";
|
echo '</tr>' . "\n";
|
||||||
@@ -116,6 +117,59 @@ function PMA_TableHeader($db_is_information_schema = false)
|
|||||||
$GLOBALS['structure_tbl_col_cnt'] = $cnt + $action_colspan + 3;
|
$GLOBALS['structure_tbl_col_cnt'] = $cnt + $action_colspan + 3;
|
||||||
} // end function PMA_TableHeader()
|
} // end function PMA_TableHeader()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a clickable column header for table information
|
||||||
|
*
|
||||||
|
* @param string title to use for the link
|
||||||
|
* @param string corresponds to sortable data name mapped in libraries/db_info.inc.php
|
||||||
|
* @returns string link to be displayed in the table header
|
||||||
|
*/
|
||||||
|
function PMA_SortableTableHeader($title, $sort)
|
||||||
|
{
|
||||||
|
// Set some defaults
|
||||||
|
$requested_sort = 'table';
|
||||||
|
$requested_sort_order = 'ASC';
|
||||||
|
$sort_order = 'ASC';
|
||||||
|
|
||||||
|
// If the user requested a sort
|
||||||
|
if (isset($_REQUEST['sort'])) {
|
||||||
|
$requested_sort = $_REQUEST['sort'];
|
||||||
|
|
||||||
|
if (isset($_REQUEST['sort_order'])) {
|
||||||
|
$requested_sort_order = $_REQUEST['sort_order'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_img = '';
|
||||||
|
$order_link_params = array();
|
||||||
|
$order_link_params['title'] = $GLOBALS['strSort'];
|
||||||
|
|
||||||
|
// If this column was requested to be sorted.
|
||||||
|
if ($requested_sort == $sort) {
|
||||||
|
if ($requested_sort_order == 'ASC') {
|
||||||
|
$sort_order = 'DESC';
|
||||||
|
$order_img = ' <img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 's_desc.png" width="11" height="9" alt="'. $GLOBALS['strDescending'] . '" title="'. $GLOBALS['strDescending'] . '" id="soimg' . $i . '" />';
|
||||||
|
$order_link_params['onmouseover'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_asc.png\'; }';
|
||||||
|
$order_link_params['onmouseout'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_desc.png\'; }';
|
||||||
|
} else {
|
||||||
|
$order_img = ' <img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 's_asc.png" width="11" height="9" alt="'. $GLOBALS['strAscending'] . '" title="'. $GLOBALS['strAscending'] . '" id="soimg' . $i . '" />';
|
||||||
|
$order_link_params['onmouseover'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_desc.png\'; }';
|
||||||
|
$order_link_params['onmouseout'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_asc.png\'; }';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$_url_params = array(
|
||||||
|
'db' => $_REQUEST['db'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$url = 'db_structure.php'.PMA_generate_common_url($_url_params);
|
||||||
|
// We set the position back to 0 every time they sort.
|
||||||
|
$url .= "&pos=0&sort=$sort&sort_order=$sort_order";
|
||||||
|
|
||||||
|
return PMA_linkOrButton($url, $title . $order_img, $order_link_params);
|
||||||
|
}
|
||||||
|
|
||||||
$titles = array();
|
$titles = array();
|
||||||
if (true == $cfg['PropertiesIconic']) {
|
if (true == $cfg['PropertiesIconic']) {
|
||||||
$titles['Browse'] = '<img class="icon" width="16" height="16" src="' .$pmaThemeImage . 'b_browse.png" alt="' . $strBrowse . '" title="' . $strBrowse . '" />';
|
$titles['Browse'] = '<img class="icon" width="16" height="16" src="' .$pmaThemeImage . 'b_browse.png" alt="' . $strBrowse . '" title="' . $strBrowse . '" />';
|
||||||
@@ -160,11 +214,19 @@ if (true == $cfg['PropertiesIconic']) {
|
|||||||
/**
|
/**
|
||||||
* Displays the tables list
|
* Displays the tables list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$_url_params = array(
|
$_url_params = array(
|
||||||
'pos' => $pos,
|
'pos' => $pos,
|
||||||
'db' => $db);
|
'db' => $db);
|
||||||
|
|
||||||
|
// Add the sort options if they exists
|
||||||
|
if ($_REQUEST['sort']) {
|
||||||
|
$_url_params['sort'] = $_REQUEST['sort'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_REQUEST['sort_order']) {
|
||||||
|
$_url_params['sort_order'] = $_REQUEST['sort_order'];
|
||||||
|
}
|
||||||
|
|
||||||
PMA_listNavigator($total_num_tables, $pos, $_url_params, 'db_structure.php', 'frame_content', $GLOBALS['cfg']['MaxTableList']);
|
PMA_listNavigator($total_num_tables, $pos, $_url_params, 'db_structure.php', 'frame_content', $GLOBALS['cfg']['MaxTableList']);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@@ -241,10 +241,12 @@ function PMA_usort_comparison_callback($a, $b)
|
|||||||
* @param resource $link mysql link
|
* @param resource $link mysql link
|
||||||
* @param integer $limit_offset zero-based offset for the count
|
* @param integer $limit_offset zero-based offset for the count
|
||||||
* @param boolean|integer $limit_count number of tables to return
|
* @param boolean|integer $limit_count number of tables to return
|
||||||
|
* @param string $sort_by table attribute to sort by
|
||||||
|
* @param string $sort_order direction to sort (ASC or DESC)
|
||||||
* @return array list of tables in given db(s)
|
* @return array list of tables in given db(s)
|
||||||
*/
|
*/
|
||||||
function PMA_DBI_get_tables_full($database, $table = false,
|
function PMA_DBI_get_tables_full($database, $table = false, $tbl_is_group = false, $link = null,
|
||||||
$tbl_is_group = false, $link = null, $limit_offset = 0, $limit_count = false)
|
$limit_offset = 0, $limit_count = false, $sort_by = 'Name', $sort_order = 'ASC')
|
||||||
{
|
{
|
||||||
require_once './libraries/Table.class.php';
|
require_once './libraries/Table.class.php';
|
||||||
|
|
||||||
@@ -311,9 +313,37 @@ function PMA_DBI_get_tables_full($database, $table = false,
|
|||||||
WHERE ' . (PMA_IS_WINDOWS ? '' : 'BINARY') . ' `TABLE_SCHEMA` IN (\'' . implode("', '", $this_databases) . '\')
|
WHERE ' . (PMA_IS_WINDOWS ? '' : 'BINARY') . ' `TABLE_SCHEMA` IN (\'' . implode("', '", $this_databases) . '\')
|
||||||
' . $sql_where_table;
|
' . $sql_where_table;
|
||||||
|
|
||||||
|
// Sort the tables
|
||||||
|
if ($sort_by == 'Name' && $GLOBALS['cfg']['NaturalOrder']) {
|
||||||
|
// This crazy bit of SQL was inspired by a post here:
|
||||||
|
// http://forums.mysql.com/read.php?10,34908,35959#msg-35959
|
||||||
|
|
||||||
|
// Find the longest table name
|
||||||
|
$max_name_sql = "SELECT MAX(LENGTH(TABLE_NAME)) FROM `information_schema`.`TABLES`
|
||||||
|
WHERE `TABLE_SCHEMA` IN ('" . implode("', '", $this_databases) . "')";
|
||||||
|
$max_name_array = PMA_DBI_fetch_result($max_name_sql);
|
||||||
|
$max_name_length = $max_name_array[0];
|
||||||
|
|
||||||
|
// Put the CASE statement SQL together.
|
||||||
|
$sql_case = '';
|
||||||
|
for ($i = 1; $i < $max_name_length; $i++) {
|
||||||
|
$sql_case .= " when substr(Name, $i) between '0' and '9' then $i";
|
||||||
|
}
|
||||||
|
$sql_case .= " ELSE $max_name_length end) ";
|
||||||
|
|
||||||
|
// Add the CASE statement to the main SQL
|
||||||
|
$sql .= " ORDER BY left(Name, (CASE ";
|
||||||
|
$sql .= $sql_case . "-1) $sort_order, 0+substr(Name, CASE";
|
||||||
|
$sql .= $sql_case . $sort_order;
|
||||||
|
} else {
|
||||||
|
// Just let MySQL sort as it normally does
|
||||||
|
$sql .= " ORDER BY $sort_by $sort_order";
|
||||||
|
}
|
||||||
|
|
||||||
if ($limit_count) {
|
if ($limit_count) {
|
||||||
$sql .= ' LIMIT ' . $limit_count . ' OFFSET ' . $limit_offset;
|
$sql .= ' LIMIT ' . $limit_count . ' OFFSET ' . $limit_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tables = PMA_DBI_fetch_result($sql, array('TABLE_SCHEMA', 'TABLE_NAME'),
|
$tables = PMA_DBI_fetch_result($sql, array('TABLE_SCHEMA', 'TABLE_NAME'),
|
||||||
null, $link);
|
null, $link);
|
||||||
unset($sql_where_table, $sql);
|
unset($sql_where_table, $sql);
|
||||||
@@ -335,6 +365,31 @@ function PMA_DBI_get_tables_full($database, $table = false,
|
|||||||
|
|
||||||
$each_tables = PMA_DBI_fetch_result($sql, 'Name', null, $link);
|
$each_tables = PMA_DBI_fetch_result($sql, 'Name', null, $link);
|
||||||
|
|
||||||
|
// Sort naturally if the config allows it and we're sorting
|
||||||
|
// the Name column.
|
||||||
|
if ($sort_by == 'Name' && $GLOBALS['cfg']['NaturalOrder']) {
|
||||||
|
uksort($each_tables, 'strnatcasecmp');
|
||||||
|
|
||||||
|
if ($sort_order == 'DESC') {
|
||||||
|
$each_tables = array_reverse($each_tables);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Prepare to sort by creating array of the selected sort
|
||||||
|
// value to pass to array_multisort
|
||||||
|
foreach ($each_tables as $table_name => $table_data) {
|
||||||
|
${$sort_by}[$table_name] = strtolower($table_data[$sort_by]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sort_order == 'DESC') {
|
||||||
|
array_multisort($$sort_by, SORT_DESC, $each_tables);
|
||||||
|
} else {
|
||||||
|
array_multisort($$sort_by, SORT_ASC, $each_tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup the temporary sort array
|
||||||
|
unset($$sort_by);
|
||||||
|
}
|
||||||
|
|
||||||
if ($limit_count) {
|
if ($limit_count) {
|
||||||
$each_tables = array_slice($each_tables, $limit_offset, $limit_count);
|
$each_tables = array_slice($each_tables, $limit_offset, $limit_count);
|
||||||
}
|
}
|
||||||
@@ -396,12 +451,6 @@ function PMA_DBI_get_tables_full($database, $table = false,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($GLOBALS['cfg']['NaturalOrder']) {
|
|
||||||
foreach ($tables as $key => $val) {
|
|
||||||
uksort($tables[$key], 'strnatcasecmp');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache table data
|
// cache table data
|
||||||
// so PMA_Table does not require to issue SHOW TABLE STATUS again
|
// so PMA_Table does not require to issue SHOW TABLE STATUS again
|
||||||
PMA_Table::$cache = array_merge_recursive(PMA_Table::$cache, $tables);
|
PMA_Table::$cache = array_merge_recursive(PMA_Table::$cache, $tables);
|
||||||
|
@@ -197,13 +197,36 @@ if (true === $cfg['SkipLockedTables']) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (! isset($sot_ready)) {
|
if (! isset($sot_ready)) {
|
||||||
|
|
||||||
|
// Set some sorting defaults
|
||||||
|
$sort = 'name';
|
||||||
|
$sort_order = 'ASC';
|
||||||
|
|
||||||
|
if ($_REQUEST['sort']) {
|
||||||
|
$sortable_name_mappings = array(
|
||||||
|
'table' => 'Name',
|
||||||
|
'records' => 'Rows',
|
||||||
|
'type' => 'Engine',
|
||||||
|
'collation' => 'Collation',
|
||||||
|
'size' => 'Data_length',
|
||||||
|
'overhead' => 'Data_free'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make sure the sort type is implemented
|
||||||
|
if ($sort = $sortable_name_mappings[$_REQUEST['sort']]) {
|
||||||
|
if ($_REQUEST['sort_order'] == 'DESC') {
|
||||||
|
$sort_order = 'DESC';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (! empty($tbl_group) && ! $cfg['ShowTooltipAliasTB']) {
|
if (! empty($tbl_group) && ! $cfg['ShowTooltipAliasTB']) {
|
||||||
// only tables for selected group
|
// only tables for selected group
|
||||||
$tables = PMA_DBI_get_tables_full($db, $tbl_group, true);
|
$tables = PMA_DBI_get_tables_full($db, $tbl_group, true, null, 0, false, $sort, $sort_order);
|
||||||
} elseif (! empty($tbl_group) && $cfg['ShowTooltipAliasTB']) {
|
} elseif (! empty($tbl_group) && $cfg['ShowTooltipAliasTB']) {
|
||||||
// only tables for selected group,
|
// only tables for selected group,
|
||||||
// but grouping is done on comment ...
|
// but grouping is done on comment ...
|
||||||
$tables = PMA_DBI_get_tables_full($db, $tbl_group, 'comment');
|
$tables = PMA_DBI_get_tables_full($db, $tbl_group, 'comment', null, 0, false, $sort, $sort_order);
|
||||||
} else {
|
} else {
|
||||||
// all tables in db
|
// all tables in db
|
||||||
// - get the total number of tables
|
// - get the total number of tables
|
||||||
@@ -218,10 +241,10 @@ if (! isset($sot_ready)) {
|
|||||||
*
|
*
|
||||||
* @todo Page selector for table names?
|
* @todo Page selector for table names?
|
||||||
*/
|
*/
|
||||||
$tables = PMA_DBI_get_tables_full($db, false, false, null, 0, false);
|
$tables = PMA_DBI_get_tables_full($db, false, false, null, 0, false, $sort, $sort_order);
|
||||||
} else {
|
} else {
|
||||||
// fetch the details for a possible limited subset
|
// fetch the details for a possible limited subset
|
||||||
$tables = PMA_DBI_get_tables_full($db, false, false, null, $pos, true);
|
$tables = PMA_DBI_get_tables_full($db, false, false, null, $pos, true, $sort, $sort_order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user