From 06c4939e3f6b06c7ff44c8a6cb5e8e303808888a Mon Sep 17 00:00:00 2001 From: Kasun Chathuranga Date: Tue, 18 Jun 2013 12:27:33 +0530 Subject: [PATCH 1/7] Show database name in 'Check referential integrity' operation as it already supports cross database relations --- libraries/operations.lib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/operations.lib.php b/libraries/operations.lib.php index 79da986943..60e5c6998c 100644 --- a/libraries/operations.lib.php +++ b/libraries/operations.lib.php @@ -1403,8 +1403,8 @@ function PMA_getHtmlForReferentialIntegrityCheck($foreign, $url_params) . '' - . $master . ' -> ' . $arr['foreign_table'] . '.' - . $arr['foreign_field'] + . $master . ' -> ' . $arr['foreign_db'] . '.' + . $arr['foreign_table'] . '.' . $arr['foreign_field'] . '' . "\n"; } // foreach $foreign $html_output .= ''; From 4dc2b2ecc42261fbf00e6fc823427f7393bc024b Mon Sep 17 00:00:00 2001 From: Kasun Chathuranga Date: Tue, 18 Jun 2013 12:31:26 +0530 Subject: [PATCH 2/7] Make 'full name' optional in getUniqueColumns() method as sometimes full name is not required --- libraries/Table.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/Table.class.php b/libraries/Table.class.php index 1f85d52b10..ef145efdba 100644 --- a/libraries/Table.class.php +++ b/libraries/Table.class.php @@ -1314,10 +1314,11 @@ class PMA_Table * - UNIQUE(x,y) // NONE * * @param bool $backquoted whether to quote name with backticks `` + * @param bool $fullName whether to include full name of the table as a prefix * * @return array */ - public function getUniqueColumns($backquoted = true) + public function getUniqueColumns($backquoted = true, $fullName = true) { $sql = $GLOBALS['dbi']->getTableIndexesSql( $this->getDbName(), @@ -1335,7 +1336,7 @@ class PMA_Table if (count($index) > 1) { continue; } - $return[] = $this->getFullName($backquoted) . '.' + $return[] = ($fullName ? $this->getFullName($backquoted) . '.' : '') . ($backquoted ? PMA_Util::backquote($index[0]) : $index[0]); } From 1e0e37c14a53e5fa7b6ae32c800470e028c6ec2e Mon Sep 17 00:00:00 2001 From: Kasun Chathuranga Date: Wed, 19 Jun 2013 09:38:35 +0530 Subject: [PATCH 3/7] Improved relation view interface --- js/tbl_relation.js | 100 +++++++- tbl_relation.php | 369 ++++++++++++++++++----------- themes/original/css/common.css.php | 5 + themes/pmahomme/css/common.css.php | 5 + 4 files changed, 333 insertions(+), 146 deletions(-) diff --git a/js/tbl_relation.js b/js/tbl_relation.js index 7d72a1e872..0a133ac694 100644 --- a/js/tbl_relation.js +++ b/js/tbl_relation.js @@ -5,30 +5,112 @@ */ function show_hide_clauses($thisDropdown) { - // here, one span contains the label and the clause dropdown - // and we have one span for ON DELETE and one for ON UPDATE - // - if ($thisDropdown.val() !== '') { - $thisDropdown.parent().nextAll('span').show(); - } else { + if ($thisDropdown.val() == '') { $thisDropdown.parent().nextAll('span').hide(); + } else { + if ($thisDropdown.is('select[name^="destination_foreign_column"]')) { + $thisDropdown.parent().nextAll('span').show(); + } } } +/** + * Retrieves and populates dropdowns to the left based on the selected value + * + * @param $dropdown the dropdown whose value got changed + */ +function getDropdownValues($dropdown) { + var foreignDb = null, foreignTable = null; + var $tableDd, $columnDd; + var foreign = ''; + if ($dropdown.is('select[name^="destination_foreign"]')) { + $tableDd = $dropdown.parent().find('select[name^="destination_foreign_table"]'); + $columnDd = $dropdown.parent().find('select[name^="destination_foreign_column"]'); + foreign = '_foreign'; + } else { + $tableDd = $dropdown.parent().find('select[name^="destination_table"]'); + $columnDd = $dropdown.parent().find('select[name^="destination_column"]'); + } + + if ($dropdown.is('select[name^="destination' + foreign + '_db"]')) { + foreignDb = $dropdown.val(); + if (foreignDb == '') { + setDropdownValues($tableDd, []); + setDropdownValues($columnDd, []); + return; + } + } else { + foreignDb = $dropdown.parent().find('select[name^="destination' + foreign + '_db"]').val(); + foreignTable = $dropdown.val(); + if (foreignTable == '') { + setDropdownValues($columnDd, []); + return; + } + } + var $msgbox = PMA_ajaxShowMessage(); + var $form = $dropdown.parents('form'); + var url = 'tbl_relation.php?getDropdownValues=true&ajax_request=true' + + '&token=' + $form.find('input[name="token"]').val() + + '&db=' + $form.find('input[name="db"]').val() + + '&table=' + $form.find('input[name="table"]').val() + + '&foreign=' + (foreign != '') + + '&foreignDb=' + encodeURIComponent(foreignDb) + + (foreignTable !== null ? '&foreignTable=' + encodeURIComponent(foreignTable) : ''); + $.ajax({ + url: url, + datatype: 'json', + success: function(data) { + PMA_ajaxRemoveMessage($msgbox); + if (data.success) { + if (foreignTable == null) { + setDropdownValues($tableDd, data.tables); + setDropdownValues($columnDd, []); + } else { + setDropdownValues($columnDd, data.columns); + } + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + }); +} + +function setDropdownValues($dropdown, values) { + $dropdown.empty(); + var optionsAsString = ''; + values.unshift(''); + $.each(values, function() { + optionsAsString += ""; + }) + $dropdown.append($(optionsAsString)); +} + /** * Unbind all event handlers before tearing down a page */ AJAX.registerTeardown('tbl_relation.js', function () { - $('select.referenced_column_dropdown').unbind('change'); + $('select[name^="destination_foreign"]').unbind('change'); + $('select[name^="destination_db"],' + + ' select[name^="destination_table"],' + + ' select[name^="destination_foreign_db"],' + + ' select[name^="destination_foreign_table"]').unbind('change'); }); AJAX.registerOnload('tbl_relation.js', function () { // initial display - $('select.referenced_column_dropdown').each(function (index, one_dropdown) { + $('select[name^="destination_foreign_column"]').each(function (index, one_dropdown) { show_hide_clauses($(one_dropdown)); }); // change - $('select.referenced_column_dropdown').change(function () { + $('select[name^="destination_foreign"]').change(function () { show_hide_clauses($(this)); }); + + $('select[name^="destination_db"],' + + ' select[name^="destination_table"],' + + ' select[name^="destination_foreign_db"],' + + ' select[name^="destination_foreign_table"]') + .change(function() { + getDropdownValues($(this)); + }); }); diff --git a/tbl_relation.php b/tbl_relation.php index 3334fb804a..fa1846fd7d 100644 --- a/tbl_relation.php +++ b/tbl_relation.php @@ -9,8 +9,6 @@ * for internal relations (but foreign keys relations are correct) * @todo foreign key constraints require both fields being of equal type and size * @todo check foreign fields to be from same type and size, all other makes no sense - * @todo add an link to create an index required for constraints, - * or an option to do automatically * @todo if above todos are fullfilled we can add all fields meet requirements * in the select dropdown * @package PhpMyAdmin @@ -23,6 +21,59 @@ require_once 'libraries/common.inc.php'; require_once 'libraries/index.lib.php'; $response = PMA_Response::getInstance(); + +// Send table of column names to populate corresponding dropdowns depending +// on the current selection +if (isset($_REQUEST['getDropdownValues']) + && $_REQUEST['getDropdownValues'] === 'true' +) { + $foreignDb = $_REQUEST['foreignDb']; + + if (isset($_REQUEST['foreignTable'])) { // if both db and table are selected + $foreignTable = $_REQUEST['foreignTable']; + $table_obj = new PMA_Table($foreignTable, $foreignDb); + $columns = array(); + foreach ($table_obj->getUniqueColumns(false, false) as $column) { + $columns[] = htmlspecialchars($column); + } + $response->addJSON('columns', $columns); + + } else { // if only the db is selected + $foreign = isset($_REQUEST['foreign']) && $_REQUEST['foreign'] === 'true'; + if ($foreign) { + $query = 'SHOW TABLE STATUS FROM ' . PMA_Util::backquote($foreignDb); + $tbl_storage_engine = strtoupper( + PMA_Table::sGetStatusInfo( + $_REQUEST['db'], + $_REQUEST['table'], + 'Engine' + ) + ); + } else { + $query = 'SHOW TABLES FROM ' . PMA_Util::backquote($foreignDb); + } + $tables_rs = $GLOBALS['dbi']->query( + $query, + null, + PMA_DatabaseInterface::QUERY_STORE + ); + $tables = array(); + while ($row = $GLOBALS['dbi']->fetchRow($tables_rs)) { + if ($foreign) { + if (isset($row[1]) + && strtoupper($row[1]) == $tbl_storage_engine + ) { + $tables[] = htmlspecialchars($row[0]); + } + } else { + $tables[] = htmlspecialchars($row[0]); + } + } + $response->addJSON('tables', $tables); + } + exit; +} + $header = $response->getHeader(); $scripts = $header->getScripts(); $scripts->addFile('tbl_relation.js'); @@ -32,8 +83,12 @@ $scripts->addFile('indexes.js'); * Sets globals from $_POST */ $post_params = array( - 'destination', - 'destination_foreign', + 'destination_db', + 'destination_table', + 'destination_column', + 'destination_foreign_db', + 'destination_foreign_table', + 'destination_foreign_column', 'display_field', 'fields_name', 'on_delete', @@ -84,18 +139,20 @@ $multi_edit_columns_name = isset($_REQUEST['fields_name']) $html_output = ''; // u p d a t e s f o r I n t e r n a l r e l a t i o n s -if (isset($destination) && $cfgRelation['relwork']) { +if (isset($destination_db) && $cfgRelation['relwork']) { - foreach ($destination as $master_field_md5 => $foreign_string) { + foreach ($destination_db as $master_field_md5 => $foreign_db) { $upd_query = false; // Map the fieldname's md5 back to its real name $master_field = $multi_edit_columns_name[$master_field_md5]; - if (! empty($foreign_string)) { - $foreign_string = trim($foreign_string, '`'); - list($foreign_db, $foreign_table, $foreign_field) - = explode('.', $foreign_string); + $foreign_table = $destination_table[$master_field_md5]; + $foreign_field = $destination_column[$master_field_md5]; + if (! empty($foreign_db) + && ! empty($foreign_table) + && ! empty($foreign_field) + ) { if (! isset($existrel[$master_field])) { $upd_query = 'INSERT INTO ' . PMA_Util::backquote($GLOBALS['cfgRelation']['db']) @@ -109,7 +166,11 @@ if (isset($destination) && $cfgRelation['relwork']) { . '\'' . PMA_Util::sqlAddSlashes($foreign_db) . '\', ' . '\'' . PMA_Util::sqlAddSlashes($foreign_table) . '\',' . '\'' . PMA_Util::sqlAddSlashes($foreign_field) . '\')'; - } elseif ($existrel[$master_field]['foreign_db'] . '.' .$existrel[$master_field]['foreign_table'] . '.' . $existrel[$master_field]['foreign_field'] != $foreign_string) { + + } elseif ($existrel[$master_field]['foreign_db'] != $foreign_db + || $existrel[$master_field]['foreign_table'] != $foreign_table + || $existrel[$master_field]['foreign_field'] != $foreign_field + ) { $upd_query = 'UPDATE ' . PMA_Util::backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_Util::backquote($cfgRelation['relation']) . ' SET' @@ -119,7 +180,8 @@ if (isset($destination) && $cfgRelation['relwork']) { . PMA_Util::sqlAddSlashes($foreign_table) . '\', ' . ' foreign_field = \'' . PMA_Util::sqlAddSlashes($foreign_field) . '\' ' - . ' WHERE master_db = \'' . PMA_Util::sqlAddSlashes($db) . '\'' + . ' WHERE master_db = \'' + . PMA_Util::sqlAddSlashes($db) . '\'' . ' AND master_table = \'' . PMA_Util::sqlAddSlashes($table) . '\'' . ' AND master_field = \'' @@ -144,19 +206,22 @@ if (isset($destination) && $cfgRelation['relwork']) { // (for now, one index name only; we keep the definitions if the // foreign db is not the same) -if (isset($_REQUEST['destination_foreign'])) { +if (isset($destination_foreign_db)) { $display_query = ''; $seen_error = false; - foreach ($_REQUEST['destination_foreign'] as $master_field_md5 => $foreign_string) { + foreach ($destination_foreign_db as $master_field_md5 => $foreign_db) { $create = false; $drop = false; // Map the fieldname's md5 back to it's real name $master_field = $multi_edit_columns_name[$master_field_md5]; - if (! empty($foreign_string)) { - list($foreign_db, $foreign_table, $foreign_field) - = PMA_backquoteSplit($foreign_string); + $foreign_table = $destination_foreign_table[$master_field_md5]; + $foreign_field = $destination_foreign_column[$master_field_md5]; + if (! empty($foreign_db) + && ! empty($foreign_table) + && ! empty($foreign_field) + ) { if (! isset($existrel_foreign[$master_field])) { // no key defined for this field $create = true; @@ -290,10 +355,10 @@ if ($cfgRelation['displaywork'] && isset($display_field)) { } // end if // If we did an update, refresh our data -if (isset($destination) && $cfgRelation['relwork']) { +if (isset($destination_db) && $cfgRelation['relwork']) { $existrel = PMA_getForeigners($db, $table, '', 'internal'); } -if (isset($destination_foreign) +if (isset($destination_foreign_db) && PMA_Util::isForeignKeySupported($tbl_storage_engine) ) { $existrel_foreign = PMA_getForeigners($db, $table, '', 'foreign'); @@ -312,57 +377,6 @@ if ($cfgRelation['displaywork']) { $html_output .= '
' . "\n" . PMA_generate_common_hidden_inputs($db, $table); - -// relations - -if ($cfgRelation['relwork'] - || PMA_Util::isForeignKeySupported($tbl_storage_engine) -) { - // To choose relations we first need all tables names in current db - // and if the main table supports foreign keys - // we use SHOW TABLE STATUS because we need to find other tables of the - // same engine. - - if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) { - $tab_query = 'SHOW TABLE STATUS FROM ' . PMA_Util::backquote($db); - // [0] of the row is the name - // [1] is the type - } else { - $tab_query = 'SHOW TABLES FROM ' . PMA_Util::backquote($db); - // [0] of the row is the name - } - - $tab_rs = $GLOBALS['dbi']->query( - $tab_query, null, PMA_DatabaseInterface::QUERY_STORE - ); - $selectboxall[] = ''; - $selectboxall_foreign[] = ''; - - while ($curr_table = $GLOBALS['dbi']->fetchRow($tab_rs)) { - $current_table = new PMA_Table($curr_table[0], $db); - - // explicitely ask for non-quoted list of indexed columns - $selectboxall = array_merge( - $selectboxall, - $current_table->getUniqueColumns($backquoted = false) - ); - - // if foreign keys are supported, collect all keys from other - // tables of the same engine - if (PMA_Util::isForeignKeySupported($tbl_storage_engine) - && isset($curr_table[1]) - && strtoupper($curr_table[1]) == $tbl_storage_engine - ) { - // explicitely ask for non-quoted list of indexed columns - // need to obtain backquoted values to support dots inside values - $selectboxall_foreign = array_merge( - $selectboxall_foreign, - $current_table->getIndexedColumns($backquoted = true) - ); - } - } // end while over tables -} // end if - // Now find out the columns of our $table // need to use PMA_DatabaseInterface::QUERY_STORE with $GLOBALS['dbi']->numRows() in mysqli $columns = $GLOBALS['dbi']->getColumns($db, $table); @@ -376,7 +390,7 @@ if (count($columns) > 0) { $saved_row_cnt = count($save_row); $html_output .= '
' . '' . __('Relations'). '' - . '' + . '
' . ''; if ($cfgRelation['relwork']) { @@ -417,84 +431,133 @@ if (count($columns) > 0) { $odd_row = ! $odd_row; if ($cfgRelation['relwork']) { - $html_output .= ''; + $html_output .= PMA_generateRelationalDropdown( + 'destination_db[' . $myfield_md5 . ']', + $GLOBALS['pma']->databases, + $foreign_db + ); + // end of database dropdown + + // table dropdown + $tables = array(); + if ($foreign_db) { + if (isset($existrel[$myfield])) { + $foreign_table = $existrel[$myfield]['foreign_table']; + } + $tables_rs = $GLOBALS['dbi']->query( + 'SHOW TABLES FROM ' . PMA_Util::backquote($foreign_db), + null, + PMA_DatabaseInterface::QUERY_STORE + ); + while ($row = $GLOBALS['dbi']->fetchRow($tables_rs)) { + $tables[] = $row[0]; + } + } + $html_output .= PMA_generateRelationalDropdown( + 'destination_table[' . $myfield_md5 . ']', + $tables, + $foreign_table + ); + // end of table dropdown + + // column dropdown + $columns = array(); + if ($foreign_db && $foreign_table) { + if (isset($existrel[$myfield])) { + $foreign_column = $existrel[$myfield]['foreign_field']; + } + $table_obj = new PMA_Table($foreign_table, $foreign_db); + $columns = $table_obj->getUniqueColumns(false, false); + } + $html_output .= PMA_generateRelationalDropdown( + 'destination_column[' . $myfield_md5 . ']', + $columns, + $foreign_column + ); + // end of column dropdown + + $html_output .= ''; } // end if (internal relations) if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) { $html_output .= '
' . __('Column') . ''; - // if the link defined in relationtable points to a foreign field - // that is not a key in the foreign table, we show the link - // (will not be shown with an arrow) - if ($foreign_field && !$seen_key) { - $html_output .= ''. "\n"; + $foreign_db = false; + $foreign_table = false; + $foreign_column = false; + + // database dropdown + if (isset($existrel[$myfield])) { + $foreign_db = $existrel[$myfield]['foreign_db']; + } else { + $foreign_db = $db; } - $html_output .= '' - . ''; - if (!empty($save_row[$i]['Key'])) { - $html_output .= '' - . '' - . ''; + $html_output .= PMA_generateRelationalDropdown( + 'destination_foreign_table[' . $myfield_md5 . ']', + $tables, + $foreign_table + ); + // end of foreign table dropdown + + // foreign column dropdown + $columns = array(); + if ($foreign_db && $foreign_table) { + if (isset($existrel_foreign[$myfield])) { + $foreign_column = $existrel_foreign[$myfield]['foreign_field']; + } + $table_obj = new PMA_Table($foreign_table, $foreign_db); + $columns = $table_obj->getUniqueColumns(false, false); + } + $html_output .= PMA_generateRelationalDropdown( + 'destination_foreign_column[' . $myfield_md5 . ']', + $columns, + $foreign_column + ); + $html_output .= ''; + // end of foreign column dropdown // For constraint name - $html_output .= ''; + $html_output .= ''; $constraint_name = isset($existrel_foreign[$myfield]['constraint']) ? $existrel_foreign[$myfield]['constraint'] : ''; $html_output .= __('Constraint name'); @@ -503,7 +566,7 @@ if (count($columns) > 0) { . ' value="' . $constraint_name . '"/>'; $html_output .= '' . "\n"; - $html_output .= ''; + $html_output .= ''; // For ON DELETE and ON UPDATE, the default action // is RESTRICT as per MySQL doc; however, a SHOW CREATE TABLE // won't display the clause if it's set as RESTRICT. @@ -517,7 +580,7 @@ if (count($columns) > 0) { ); $html_output .= '' . "\n"; - $html_output .= '' . "\n"; + $html_output .= '' . "\n"; $on_update = isset($existrel_foreign[$myfield]['on_update']) ? $existrel_foreign[$myfield]['on_update'] : 'RESTRICT'; $html_output .= PMA_generateDropdown( @@ -688,4 +751,36 @@ function PMA_getSQLToCreateForeignKey($table, $field, $foreignDb, $foreignTable, return $sql_query; } + +/** + * Creates and populates dropdowns to select foreign db/table/column + * + * @param string $name name of the dropdowns + * @param array $values dropdown values + * @param string $foreign value of the item to be selected + * + * @return string HTML for the dropdown + */ +function PMA_generateRelationalDropdown($name, $values = array(), $foreign = false) +{ + $html_output = ''; + return $html_output; +} ?> diff --git a/themes/original/css/common.css.php b/themes/original/css/common.css.php index 0925b3dec0..420e0a391e 100644 --- a/themes/original/css/common.css.php +++ b/themes/original/css/common.css.php @@ -2572,3 +2572,8 @@ div.jqplot-noData-container { text-align: center; background-color: rgba(96%, 96%, 96%, 0.3); } + +#relationalTable select { + width: 125px; + margin-right: 5px; +} diff --git a/themes/pmahomme/css/common.css.php b/themes/pmahomme/css/common.css.php index 7beb882281..b26304f30b 100644 --- a/themes/pmahomme/css/common.css.php +++ b/themes/pmahomme/css/common.css.php @@ -2778,6 +2778,11 @@ fieldset .disabled-field td { padding-: 20px; } +#relationalTable select { + width: 125px; + margin-right: 5px; +} + /* css for timepicker */ .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; } .ui-timepicker-div dl { text-align: ; } From 2570db554c538b9d462b48905bca0ce2c7ee7056 Mon Sep 17 00:00:00 2001 From: Kasun Chathuranga Date: Wed, 19 Jun 2013 09:55:40 +0530 Subject: [PATCH 4/7] Improve comments on the behavior of new relation view interface --- js/tbl_relation.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/js/tbl_relation.js b/js/tbl_relation.js index 0a133ac694..2925096ceb 100644 --- a/js/tbl_relation.js +++ b/js/tbl_relation.js @@ -23,25 +23,30 @@ function getDropdownValues($dropdown) { var foreignDb = null, foreignTable = null; var $tableDd, $columnDd; var foreign = ''; + // if the changed dropdown is for foreign key constraints if ($dropdown.is('select[name^="destination_foreign"]')) { $tableDd = $dropdown.parent().find('select[name^="destination_foreign_table"]'); $columnDd = $dropdown.parent().find('select[name^="destination_foreign_column"]'); foreign = '_foreign'; - } else { + } else { // internal relations $tableDd = $dropdown.parent().find('select[name^="destination_table"]'); $columnDd = $dropdown.parent().find('select[name^="destination_column"]'); } + // if the changed dropdown is a database selector if ($dropdown.is('select[name^="destination' + foreign + '_db"]')) { foreignDb = $dropdown.val(); + // if no database is selected empty table and column dropdowns if (foreignDb == '') { setDropdownValues($tableDd, []); setDropdownValues($columnDd, []); return; } - } else { - foreignDb = $dropdown.parent().find('select[name^="destination' + foreign + '_db"]').val(); + } else { // if a table selector + foreignDb = $dropdown.parent() + .find('select[name^="destination' + foreign + '_db"]').val(); foreignTable = $dropdown.val(); + // if no table is selected empty the column dropdown if (foreignTable == '') { setDropdownValues($columnDd, []); return; @@ -55,17 +60,22 @@ function getDropdownValues($dropdown) { + '&table=' + $form.find('input[name="table"]').val() + '&foreign=' + (foreign != '') + '&foreignDb=' + encodeURIComponent(foreignDb) - + (foreignTable !== null ? '&foreignTable=' + encodeURIComponent(foreignTable) : ''); + + (foreignTable !== null ? + '&foreignTable=' + encodeURIComponent(foreignTable) : '' + ); $.ajax({ url: url, datatype: 'json', success: function(data) { PMA_ajaxRemoveMessage($msgbox); if (data.success) { + // if the changed dropdown is a database selector if (foreignTable == null) { + // set values for table and column dropdowns setDropdownValues($tableDd, data.tables); setDropdownValues($columnDd, []); - } else { + } else { // if a table selector + // set values for the column dropdown setDropdownValues($columnDd, data.columns); } } else { @@ -78,6 +88,7 @@ function getDropdownValues($dropdown) { function setDropdownValues($dropdown, values) { $dropdown.empty(); var optionsAsString = ''; + // add an empty string to the beginning for empty selection values.unshift(''); $.each(values, function() { optionsAsString += ""; From 05e84653242606eeba078c73e204fe00a5a5d4e1 Mon Sep 17 00:00:00 2001 From: Kasun Chathuranga Date: Wed, 19 Jun 2013 10:49:57 +0530 Subject: [PATCH 5/7] Pass parameter values without backquotes to avoid confusions --- tbl_relation.php | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tbl_relation.php b/tbl_relation.php index fa1846fd7d..2e10eee823 100644 --- a/tbl_relation.php +++ b/tbl_relation.php @@ -225,9 +225,9 @@ if (isset($destination_foreign_db)) { if (! isset($existrel_foreign[$master_field])) { // no key defined for this field $create = true; - } elseif (PMA_Util::backquote($existrel_foreign[$master_field]['foreign_db']) != $foreign_db - || PMA_Util::backquote($existrel_foreign[$master_field]['foreign_table']) != $foreign_table - || PMA_Util::backquote($existrel_foreign[$master_field]['foreign_field']) != $foreign_field + } elseif ($existrel_foreign[$master_field]['foreign_db'] != $foreign_db + || $existrel_foreign[$master_field]['foreign_table'] != $foreign_table + || $existrel_foreign[$master_field]['foreign_field'] != $foreign_field || $_REQUEST['constraint_name'][$master_field_md5] != $existrel_foreign[$master_field]['constraint'] || ($_REQUEST['on_delete'][$master_field_md5] != (! empty($existrel_foreign[$master_field]['on_delete']) ? $existrel_foreign[$master_field]['on_delete'] : 'RESTRICT')) || ($_REQUEST['on_update'][$master_field_md5] != (! empty($existrel_foreign[$master_field]['on_update']) ? $existrel_foreign[$master_field]['on_update'] : 'RESTRICT')) @@ -297,10 +297,11 @@ if (isset($destination_foreign_db)) { // a rollback may be better here $sql_query_recreate = '# Restoring the dropped constraint...' . "\n"; $sql_query_recreate .= PMA_getSQLToCreateForeignKey( - $table, $master_field, - PMA_Util::backquote($existrel_foreign[$master_field]['foreign_db']), - PMA_Util::backquote($existrel_foreign[$master_field]['foreign_table']), - PMA_Util::backquote($existrel_foreign[$master_field]['foreign_field']), + $table, + $master_field, + $existrel_foreign[$master_field]['foreign_db'], + $existrel_foreign[$master_field]['foreign_table'], + $existrel_foreign[$master_field]['foreign_field'], $existrel_foreign[$master_field]['constraint'], $options_array[$existrel_foreign[$master_field]['on_delete']], $options_array[$existrel_foreign[$master_field]['on_update']] @@ -719,9 +720,9 @@ function PMA_getSQLToDropForeignKey($table, $fk) * * @param string $table table name * @param string $field field name - * @param string $foreignDb back-quoted foreign database name - * @param string $foreignTable back-quoted foreign table name - * @param string $foreignField back-quoted foreign field name + * @param string $foreignDb foreign database name + * @param string $foreignTable foreign table name + * @param string $foreignField foreign field name * @param string $name name of the constraint * @param string $onDelete on delete action * @param string $onUpdate on update action @@ -738,8 +739,9 @@ function PMA_getSQLToCreateForeignKey($table, $field, $foreignDb, $foreignTable, } $sql_query .= ' FOREIGN KEY (' . PMA_Util::backquote($field) . ')' - . ' REFERENCES ' . $foreignDb . '.' . $foreignTable - . '(' . $foreignField . ')'; + . ' REFERENCES ' . PMA_Util::backquote($foreignDb) + . '.' . PMA_Util::backquote($foreignTable) + . '(' . PMA_Util::backquote($foreignField) . ')'; if (! empty($onDelete)) { $sql_query .= ' ON DELETE ' . $onDelete; From 768f736bcbe5370a2bc40a45e784c3db28f21838 Mon Sep 17 00:00:00 2001 From: Kasun Chathuranga Date: Wed, 19 Jun 2013 11:54:35 +0530 Subject: [PATCH 6/7] Update FAQs to reflect the ability to set cross database relations --- doc/faq.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/faq.rst b/doc/faq.rst index 2f71a94b74..de7750d716 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -881,8 +881,7 @@ TableSeparator or disabling that feature. 3.6 What is currently not supported in phpMyAdmin about InnoDB? --------------------------------------------------------------- -In Relation view, being able to choose a table in another database, or -having more than one index column in the foreign key. In Query-by- +In Relation view, having more than one index column in the foreign key. In Query-by- example (Query), automatic generation of the query LEFT JOIN from the foreign table. From 71e4dd5f526831fc8a33c1fb7e85660a0ba49253 Mon Sep 17 00:00:00 2001 From: Kasun Chathuranga Date: Wed, 19 Jun 2013 12:07:09 +0530 Subject: [PATCH 7/7] Update FAQs to reflect new process of selecting foreign columns --- doc/faq.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/faq.rst b/doc/faq.rst index de7750d716..0fce4dfa64 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -1377,7 +1377,7 @@ look for the word "upload" in this document. --------------------------------------------------------- Here is an example with the tables persons, towns and countries, all -located in the database mydb. If you don't have a ``pma__relation`` +located in the database "mydb". If you don't have a ``pma__relation`` table, create it as explained in the configuration section. Then create the example tables: @@ -1415,8 +1415,10 @@ create the example tables: To setup appropriate links and display information: * on table "REL\_persons" click Structure, then Relation view -* in Links, for "town\_code" choose "REL\_towns->code" -* in Links, for "country\_code" choose "REL\_countries->country\_code" +* for "town\_code", choose from dropdowns, "mydb", "REL\_towns", "code" + for foreign database, table and column respectively +* for "country\_code", choose from dropdowns, "mydb", "REL\_countries", + "country\_code" for foreign database, table and column respectively * on table "REL\_towns" click Structure, then Relation view * in "Choose column to display", choose "description" * repeat the two previous steps for table "REL\_countries"