diff --git a/Documentation.html b/Documentation.html index 5195df93dc..8f7e66f871 100644 --- a/Documentation.html +++ b/Documentation.html @@ -1086,9 +1086,9 @@ ALTER TABLE `pma_column_comments`
Since release 3.5.0 phpMyAdmin can be configured to remember several things - (table sorting + (sorted column $cfg['RememberSorting'] - , etc.) for browsing tables. + , column order, and column visibility from a database table) for browsing tables. Without configuring the storage, these features still can be used, but the values will disappear after you logout.

@@ -1223,6 +1223,15 @@ CREATE DATABASE,ALTER DATABASE,DROP DATABASE
+
$cfg['Servers'][$i]['MaxTableUiprefs'] integer +
+
Maximum number of rows saved in $cfg['Servers'][$i]['table_uiprefs'] table.

+ + When tables are dropped or renamed, table_uiprefs may contain invalid + data (referring to tables which no longer exist).
+ We only keep this number of newest rows in table_uiprefs and automatically delete older rows.
+
$cfg['Servers'][$i]['verbose_check'] boolean
Because release 2.5.0 introduced the new MIME-transformation support, the @@ -1636,7 +1645,7 @@ CREATE DATABASE,ALTER DATABASE,DROP DATABASE
$cfg['ShowAll'] boolean
Defines whether a user should be displayed a - "show all (records)" button in browse mode or not.
+ "show all (rows)" button in browse mode or not.
$cfg['MaxRows'] integer
Number of rows displayed when browsing a result set. If the result set @@ -3230,7 +3239,7 @@ the mysql_upgrade command on the server.

please upgrade to a plain revision.

- 2.5 Each time I want to insert or change a record or drop a database + 2.5 Each time I want to insert or change a row or drop a database or a table, an error 404 (page not found) is displayed or, with HTTP or cookie authentication, I'm asked to log in again. What's wrong?

@@ -3469,7 +3478,7 @@ have either the APC extension can use it for the Edit and Delete links.

- 3.11 The number of records for InnoDB tables is not correct.

+ 3.11 The number of rows for InnoDB tables is not correct.

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 @@ -5020,8 +5029,8 @@ Jakub Wilk, Thomas Michael Winningham, Vilius Zigmantas, "Manuzhai".

  • Field - one part of divided data/columns.
  • foreign key - - a field or group of fields in a database record that point to a key - field or group of fields forming a key of another database record in some + - a column or group of columns in a database row that point to a key + column or group of columns forming a key of another database row in some (usually different) table.
  • FPDF (FreePDF) - the free PDF library
  • @@ -5112,7 +5121,7 @@ Jakub Wilk, Thomas Michael Winningham, Vilius Zigmantas, "Manuzhai". Internet technologies.
  • RFC 1952 - GZIP file format specification version 4.3
  • -
  • Row (record, tulpel) +
  • Row (record, tuple) - represents a single, implicitly structured data item in a table.
  • Server - a computer system that provides services to other computing diff --git a/js/makegrid.js b/js/makegrid.js index b8ca5fac19..91fa8a50b4 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -353,22 +353,31 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi * Send column preferences (column order and visibility) to the server. */ sendColPrefs: function() { - var post_params = { - ajax_request: true, - db: g.db, - table: g.table, - token: g.token, - server: g.server, - set_col_prefs: true, - table_create_time: g.tableCreateTime - }; - if (g.colOrder.length > 0) { - $.extend(post_params, { col_order: g.colOrder.toString() }); + if ($(g.t).is('.ajax')) { // only send preferences if AjaxEnable is true + var post_params = { + ajax_request: true, + db: g.db, + table: g.table, + token: g.token, + server: g.server, + set_col_prefs: true, + table_create_time: g.tableCreateTime + }; + if (g.colOrder.length > 0) { + $.extend(post_params, { col_order: g.colOrder.toString() }); + } + if (g.colVisib.length > 0) { + $.extend(post_params, { col_visib: g.colVisib.toString() }); + } + $.post('sql.php', post_params, function(data) { + if (data.success != true) { + var $temp_div = $(document.createElement('div')); + $temp_div.html(data.error); + $temp_div.addClass("error"); + PMA_ajaxShowMessage($temp_div); + } + }); } - if (g.colVisib.length > 0) { - $.extend(post_params, { col_visib: g.colVisib.toString() }); - } - $.post('sql.php', post_params); }, /** @@ -1500,6 +1509,7 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi g.cellEditHint = PMA_messages['strCellEditHint']; g.saveCellWarning = PMA_messages['strSaveCellWarning']; g.alertNonUnique = PMA_messages['strAlertNonUnique']; + g.gotoLinkText = PMA_messages['strGoToLink']; // initialize cell editing configuration g.saveCellsAtOnce = $('#save_cells_at_once').val(); @@ -1560,6 +1570,9 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi // attach to global div $(g.gDiv).append(g.cEdit); + + // add hint for grid editing feature when hovering "Edit" link in each table row + PMA_createqTip($(g.t).find('.edit_row_anchor a'), PMA_messages['strGridEditFeatureHint']); } } diff --git a/js/messages.php b/js/messages.php index e032af73ac..63fb18200e 100644 --- a/js/messages.php +++ b/js/messages.php @@ -283,6 +283,8 @@ $js_messages['strColMarkHint'] = __('Click to mark/unmark'); $js_messages['strColVisibHint'] = __('Click the drop-down arrow
    to toggle column\'s visibility'); $js_messages['strShowAllCol'] = __('Show all'); $js_messages['strAlertNonUnique'] = __('This table does not contain a unique column. Features related to the grid edit, checkbox, Edit, Copy and Delete links may not work after saving.'); +$js_messages['strGridEditFeatureHint'] = __('You can also edit most columns
    by clicking directly on their content.'); +$js_messages['strGoToLink'] = __('Go to link'); /* password generation */ $js_messages['strGeneratePassword'] = __('Generate password'); diff --git a/libraries/Table.class.php b/libraries/Table.class.php index 80ab72778a..87fb50a8b2 100644 --- a/libraries/Table.class.php +++ b/libraries/Table.class.php @@ -1266,7 +1266,7 @@ class PMA_Table " REPLACE INTO " . $pma_table . " VALUES ('" . $username . "', '" . PMA_sqlAddSlashes($this->db_name) . "', '" . PMA_sqlAddSlashes($this->name) . "', '" . - PMA_sqlAddSlashes(json_encode($this->uiprefs)) . "')"; + PMA_sqlAddSlashes(json_encode($this->uiprefs)) . "', NULL)"; $success = PMA_DBI_try_query($sql_query, $GLOBALS['controllink']); @@ -1276,6 +1276,28 @@ class PMA_Table $message->addMessage(PMA_Message::rawError(PMA_DBI_getError($GLOBALS['controllink']))); return $message; } + + // Remove some old rows in table_uiprefs if it exceeds the configured maximum rows + $sql_query = 'SELECT COUNT(*) FROM ' . $pma_table; + $rows_count = PMA_DBI_fetch_value($sql_query); + $max_rows = $GLOBALS['cfg']['Server']['MaxTableUiprefs']; + if ($rows_count > $max_rows) { + $num_rows_to_delete = $rows_count - $max_rows; + $sql_query = + ' DELETE FROM ' . $pma_table . + ' ORDER BY last_update ASC' . + ' LIMIT ' . $num_rows_to_delete; + $success = PMA_DBI_try_query($sql_query, $GLOBALS['controllink']); + + if (!$success) { + $message = PMA_Message::error(__('Failed to cleanup table UI preferences (see cfg["Server"]["MaxTableUiprefs"] documentation)')); + $message->addMessage('

    '); + $message->addMessage(PMA_Message::rawError(PMA_DBI_getError($GLOBALS['controllink']))); + print_r($message); + return $message; + } + } + return true; } diff --git a/libraries/config.default.php b/libraries/config.default.php index 0568e2d259..efb0cbb358 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -377,6 +377,19 @@ $cfg['Servers'][$i]['tracking'] = ''; */ $cfg['Servers'][$i]['userconfig'] = ''; +/** + * Maximum number of records saved in $cfg['Servers'][$i]['table_uiprefs'] table. + * + * In case where tables in databases is modified (e.g. dropped or renamed), + * table_uiprefs may contains invalid data (referring to tables which are not + * exist anymore). + * This configuration make sure that we only keep N (N = MaxTableUiprefs) + * newest record in table_uiprefs and automatically delete older records. + * + * @global integer $cfg['Servers'][$i]['userconfig'] = ''; + */ +$cfg['Servers'][$i]['MaxTableUiprefs'] = 100; + /** * set to false if you know that your pma_* tables are up to date. * This prevents compatibility checks and thereby increases performance. diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php index 6cb9f20fc8..77f53702cb 100644 --- a/libraries/config/messages.inc.php +++ b/libraries/config/messages.inc.php @@ -395,6 +395,8 @@ $strConfigServers_history_name = __('SQL query history table'); $strConfigServers_host_desc = __('Hostname where MySQL server is running'); $strConfigServers_host_name = __('Server hostname'); $strConfigServers_LogoutURL_name = __('Logout URL'); +$strConfigServers_MaxTableUiprefs_desc = __('This configuration make sure that we only keep N (N = MaxTableUiprefs) newest record in "table_uiprefs" and automatically delete older records'); +$strConfigServers_MaxTableUiprefs_name = __('Maximum number of records saved in "table_uiprefs" table'); $strConfigServers_nopassword_desc = __('Try to connect without password'); $strConfigServers_nopassword_name = __('Connect without password'); $strConfigServers_only_db_desc = __('You can use MySQL wildcard characters (% and _), escape them if you want to use their literal instances, i.e. use [kbd]\'my\_db\'[/kbd] and not [kbd]\'my_db\'[/kbd]. Using this option you can sort database list, just enter their names in order and use [kbd]*[/kbd] at the end to show the rest in alphabetical order.'); diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php index 1ccb89feab..8ab287496b 100644 --- a/libraries/config/setup.forms.php +++ b/libraries/config/setup.forms.php @@ -78,7 +78,8 @@ $forms['Servers']['Server_pmadb'] = array('Servers' => array(1 => array( 'tracking' => 'pma_tracking', 'table_coords' => 'pma_table_coords', 'pdf_pages' => 'pma_pdf_pages', - 'designer_coords' => 'pma_designer_coords'))); + 'designer_coords' => 'pma_designer_coords', + 'MaxTableUiprefs' => 100))); $forms['Servers']['Server_tracking'] = array('Servers' => array(1 => array( 'tracking_version_auto_create', 'tracking_default_statements', diff --git a/scripts/create_tables.sql b/scripts/create_tables.sql index 5db0de4e70..b0a52201fe 100644 --- a/scripts/create_tables.sql +++ b/scripts/create_tables.sql @@ -128,6 +128,7 @@ CREATE TABLE IF NOT EXISTS `pma_table_uiprefs` ( `db_name` varchar(64) NOT NULL, `table_name` varchar(64) NOT NULL, `prefs` text NOT NULL, + `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`username`,`db_name`,`table_name`) ) ENGINE=MyISAM COMMENT='Tables'' UI preferences' diff --git a/sql.php b/sql.php index 1070bda9c1..7e9c0f6486 100644 --- a/sql.php +++ b/sql.php @@ -174,12 +174,19 @@ if (isset($_REQUEST['set_col_prefs']) && $_REQUEST['set_col_prefs'] == true) { if (isset($_REQUEST['col_order'])) { $col_order = explode(',', $_REQUEST['col_order']); $retval = $pmatable->setUiProp(PMA_Table::PROP_COLUMN_ORDER, $col_order, $_REQUEST['table_create_time']); + if ($retval !== true) { + PMA_ajaxResponse($retval->getString(), false); + } } + // set column visibility if (isset($_REQUEST['col_visib'])) { $col_visib = explode(',', $_REQUEST['col_visib']); - $retval &= $pmatable->setUiProp(PMA_Table::PROP_COLUMN_VISIB, $col_visib, $_REQUEST['table_create_time']); + $retval = $pmatable->setUiProp(PMA_Table::PROP_COLUMN_VISIB, $col_visib, $_REQUEST['table_create_time']); + if ($retval !== true) { + PMA_ajaxResponse($retval->getString(), false); + } } PMA_ajaxResponse(NULL, ($retval == true));