diff --git a/libraries/Table.class.php b/libraries/Table.class.php index c7a9fb226..37db8094b 100644 --- a/libraries/Table.class.php +++ b/libraries/Table.class.php @@ -1047,5 +1047,59 @@ class PMA_Table { htmlspecialchars($old_name), htmlspecialchars($new_name)); return true; } + + /** + * Get all unique columns + * + * returns an array with all columns with unqiue content, in fact these are + * all columns being single indexed in PRIMARY or UNIQUE + * + * f.e. + * - PRIMARY(id) // id + * - UNIQUE(name) // name + * - PRIMARY(fk_id1, fk_id2) // NONE + * - UNIQUE(x,y) // NONE + * + * + * @return array + */ + public function getUniqueColumns() + { + $sql = 'SHOW INDEX FROM ' . $this->getFullName(true) . ' WHERE Non_unique = 0'; + $uniques = PMA_DBI_fetch_result($sql, array('Key_name', null), 'Column_name'); + + $return = array(); + foreach ($uniques as $index) { + if (count($index) > 1) { + continue; + } + $return[] = $this->getFullName(true) . '.' . PMA_backquote($index[0]); + } + + return $return; + } + + /** + * Get all indexed columns + * + * returns an array with all columns make use of an index, in fact only + * first columns in an index + * + * f.e. index(col1, col2) would only return col1 + * + * @return array + */ + public function getIndexedColumns() + { + $sql = 'SHOW INDEX FROM ' . $this->getFullName(true) . ' WHERE Seq_in_index = 1'; + $indexed = PMA_DBI_fetch_result($sql, 'Column_name', 'Column_name'); + + $return = array(); + foreach ($indexed as $column) { + $return[] = $this->getFullName(true) . '.' . PMA_backquote($column); + } + + return $return; + } } ?> diff --git a/tbl_relation.php b/tbl_relation.php index 66b866f59..c1cc1889e 100644 --- a/tbl_relation.php +++ b/tbl_relation.php @@ -1,7 +1,15 @@ 'CASCADE', 'SET_NULL' => 'SET NULL', 'NO_ACTION' => 'NO ACTION', 'RESTRICT' => 'RESTRICT'); +$options_array = array( + 'CASCADE' => 'CASCADE', + 'SET_NULL' => 'SET NULL', + 'NO_ACTION' => 'NO ACTION', + 'RESTRICT' => 'RESTRICT', +); /** * Generate dropdown choices @@ -44,23 +57,21 @@ $options_array = array('CASCADE' => 'CASCADE', 'SET_NULL' => 'SET NULL', 'NO_ACT */ function PMA_generate_dropdown($dropdown_question, $radio_name, $choices, $selected_value) { - echo $dropdown_question . '  '; + echo htmlspecialchars($dropdown_question) . '  '; - echo '' . "\n"; + echo '' . "\n"; - foreach ($choices AS $one_value => $one_label) { - echo '' . "\n"; + echo '>' . htmlspecialchars($one_label) . '' . "\n"; } echo '' . "\n"; - echo "\n"; } - /** * Gets the relation settings */ @@ -70,15 +81,10 @@ $cfgRelation = PMA_getRelationsParam(); /** * Updates */ - -// ensure we are positionned to our current db (since the previous reading -// of relations makes pmadb the current one, maybe depending on the MySQL version) -PMA_DBI_select_db($db); - if ($cfgRelation['relwork']) { $existrel = PMA_getForeigners($db, $table, '', 'internal'); } -if ($tbl_type=='INNODB') { +if ($tbl_type == 'INNODB') { $existrel_innodb = PMA_getForeigners($db, $table, '', 'innodb'); } if ($cfgRelation['displaywork']) { @@ -88,10 +94,13 @@ if ($cfgRelation['displaywork']) { // 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']) { - foreach ($destination AS $master_field => $foreign_string) { - if ($foreign_string != 'nix') { - list($foreign_db, $foreign_table, $foreign_field) = explode('.', $foreign_string); - if (!isset($existrel[$master_field])) { + foreach ($destination as $master_field => $foreign_string) { + $upd_query = false; + if (! empty($foreign_string)) { + $foreign_string = trim($foreign_string, '`'); + list($foreign_db, $foreign_table, $foreign_field) = + explode('`.`', $foreign_string); + if (! isset($existrel[$master_field])) { $upd_query = 'INSERT INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['relation']) . '(master_db, master_table, master_field, foreign_db, foreign_table, foreign_field)' . ' values(' @@ -116,9 +125,8 @@ if (isset($destination) && $cfgRelation['relwork']) { . ' AND master_table = \'' . PMA_sqlAddslashes($table) . '\'' . ' AND master_field = \'' . PMA_sqlAddslashes($master_field) . '\''; } // end if... else.... - if (isset($upd_query)) { - $upd_rs = PMA_query_as_cu($upd_query); - unset($upd_query); + if ($upd_query) { + PMA_query_as_cu($upd_query); } } // end while } // end if (updates for internal relations) @@ -133,8 +141,10 @@ if (isset($_REQUEST['destination_innodb'])) { $display_query = ''; $seen_error = false; foreach ($_REQUEST['destination_innodb'] as $master_field => $foreign_string) { - if ($foreign_string != 'nix') { - list($foreign_db, $foreign_table, $foreign_field) = explode('.', $foreign_string); + if (! empty($foreign_string)) { + $foreign_string = trim($foreign_string, '`'); + list($foreign_db, $foreign_table, $foreign_field) = + explode('`.`', $foreign_string); if (!isset($existrel_innodb[$master_field])) { // no key defined for this field @@ -152,11 +162,11 @@ if (isset($_REQUEST['destination_innodb'])) { . PMA_backquote($foreign_table) . '(' . PMA_backquote($foreign_field) . ')'; - if ($_REQUEST['on_delete'][$master_field] != 'nix') { - $sql_query .= ' ON DELETE ' . $options_array[$_REQUEST['on_delete'][$master_field]]; + if (! empty($_REQUEST['on_delete'][$master_field])) { + $sql_query .= ' ON DELETE ' . $options_array[$_REQUEST['on_delete'][$master_field]]; } - if ($_REQUEST['on_update'][$master_field] != 'nix') { - $sql_query .= ' ON UPDATE ' . $options_array[$_REQUEST['on_update'][$master_field]]; + if (! empty($_REQUEST['on_update'][$master_field])) { + $sql_query .= ' ON UPDATE ' . $options_array[$_REQUEST['on_update'][$master_field]]; } $sql_query .= ';'; $display_query .= $sql_query . "\n"; @@ -176,7 +186,7 @@ if (isset($_REQUEST['destination_innodb'])) { . PMA_backquote($existrel_innodb[$master_field]['constraint']) . ';'; // I tried to send both in one query but it failed - $upd_rs = PMA_DBI_query($sql_query); + PMA_DBI_query($sql_query); $display_query .= $sql_query . "\n"; // add another @@ -209,7 +219,7 @@ if (isset($_REQUEST['destination_innodb'])) { } // end if... else.... if (! empty($sql_query)) { - $upd_rs = PMA_DBI_try_query($sql_query); + PMA_DBI_try_query($sql_query); $tmp_error = PMA_DBI_getError(); if (! empty($tmp_error)) { $seen_error = true; @@ -241,9 +251,8 @@ if (isset($_REQUEST['destination_innodb'])) { // U p d a t e s f o r d i s p l a y f i e l d -if ($cfgRelation['displaywork'] - && isset($display_field)) { - +if ($cfgRelation['displaywork'] && isset($display_field)) { + $upd_query = false; if ($disp) { if ($display_field != '') { $upd_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_info']) @@ -264,8 +273,8 @@ if ($cfgRelation['displaywork'] . '\'' . PMA_sqlAddslashes($display_field) . '\')'; } - if (isset($upd_query)) { - $upd_rs = PMA_query_as_cu($upd_query); + if ($upd_query) { + PMA_query_as_cu($upd_query); } } // end if @@ -293,92 +302,35 @@ echo PMA_generate_common_hidden_inputs($db, $table); // relations -if ($cfgRelation['relwork'] || $tbl_type=='INNODB') { +if ($cfgRelation['relwork'] || $tbl_type == 'INNODB') { // To choose relations we first need all tables names in current db // and if PMA version permits and the main table is innodb, // we use SHOW TABLE STATUS because we need to find other InnoDB tables - if ($tbl_type=='INNODB') { + if ($tbl_type == 'INNODB') { $tab_query = 'SHOW TABLE STATUS FROM ' . PMA_backquote($db); - // [0] of the row is the name - // [1] is the type + // [0] of the row is the name + // [1] is the type } else { $tab_query = 'SHOW TABLES FROM ' . PMA_backquote($db); + // [0] of the row is the name } - // [0] of the row is the name $tab_rs = PMA_DBI_query($tab_query, null, PMA_DBI_QUERY_STORE); - $selectboxall['nix'] = '--'; - $selectboxall_innodb['nix'] = '--'; + $selectboxall[] = ''; + $selectboxall_innodb[] = ''; - while ($curr_table = @PMA_DBI_fetch_row($tab_rs)) { - if (($curr_table[0] != $table) && ($curr_table[0] != $cfg['Server']['relation'])) { - PMA_DBI_select_db($db); + while ($curr_table = PMA_DBI_fetch_row($tab_rs)) { + $current_table = new PMA_Table($curr_table[0], $db); - // need to use PMA_DBI_QUERY_STORE with PMA_DBI_num_rows() in mysqli - $fi_rs = PMA_DBI_query('SHOW KEYS FROM ' . PMA_backquote($curr_table[0]) . ';', null, PMA_DBI_QUERY_STORE); - if ($fi_rs && PMA_DBI_num_rows($fi_rs) > 0) { - $seen_a_primary = FALSE; - while ($curr_field = PMA_DBI_fetch_assoc($fi_rs)) { - if (isset($curr_field['Key_name']) && $curr_field['Key_name'] == 'PRIMARY') { - $seen_a_primary = TRUE; - $field_full = $db . '.' .$curr_field['Table'] . '.' . $curr_field['Column_name']; - $field_v = $curr_field['Table'] . '->' . $curr_field['Column_name']; - $selectboxall[$field_full] = $field_v; - // there could be more than one segment of the primary - // so do not break + $selectboxall = array_merge($selectboxall, $current_table->getUniqueColumns()); - // Please watch here, tbl_type is INNODB but the - // resulting value of SHOW KEYS is InnoDB - - if ($tbl_type=='INNODB' && isset($curr_table[1]) && $curr_table[1]=='InnoDB') { - $selectboxall_innodb[$field_full] = $field_v; - } - - } elseif (isset($curr_field['Non_unique']) && $curr_field['Non_unique'] == 0 && $seen_a_primary==FALSE) { - // if we can't find a primary key we take any unique one - // (in fact, we show all segments of unique keys - // and all unique keys) - $field_full = $db . '.' . $curr_field['Table'] . '.' . $curr_field['Column_name']; - $field_v = $curr_field['Table'] . '->' . $curr_field['Column_name']; - $selectboxall[$field_full] = $field_v; - if ($tbl_type=='INNODB' && isset($curr_table[1]) && $curr_table[1]=='InnoDB') { - $selectboxall_innodb[$field_full] = $field_v; - } - - // for InnoDB, any index is allowed - } elseif ($tbl_type=='INNODB' && isset($curr_table[1]) && $curr_table[1]=='InnoDB') { - $field_full = $db . '.' . $curr_field['Table'] . '.' . $curr_field['Column_name']; - $field_v = $curr_field['Table'] . '->' . $curr_field['Column_name']; - $selectboxall_innodb[$field_full] = $field_v; - - } // end if - } // end while over keys - } // end if (PMA_DBI_num_rows) - PMA_DBI_free_result($fi_rs); - unset($fi_rs); - // Mike Beck - 24.07.02: i've been asked to add all keys of the - // current table (see bug report #574851) - } elseif ($curr_table[0] == $table) { - PMA_DBI_select_db($db); - - // need to use PMA_DBI_QUERY_STORE with PMA_DBI_num_rows() in mysqli - $fi_rs = PMA_DBI_query('SHOW KEYS FROM ' . PMA_backquote($curr_table[0]) . ';', null, PMA_DBI_QUERY_STORE); - if ($fi_rs && PMA_DBI_num_rows($fi_rs) > 0) { - while ($curr_field = PMA_DBI_fetch_assoc($fi_rs)) { - $field_full = $db . '.' . $curr_field['Table'] . '.' . $curr_field['Column_name']; - $field_v = $curr_field['Table'] . '->' . $curr_field['Column_name']; - $selectboxall[$field_full] = $field_v; - if ($tbl_type=='INNODB' && isset($curr_table[1]) && $curr_table[1]=='InnoDB') { - $selectboxall_innodb[$field_full] = $field_v; - } - } // end while - } // end if (PMA_DBI_num_rows) - PMA_DBI_free_result($fi_rs); - unset($fi_rs); + if ($tbl_type == 'INNODB' + && isset($curr_table[1]) + && $curr_table[1] == 'InnoDB') { + $selectboxall_innodb = array_merge($selectboxall_innodb, $current_table->getIndexedColumns()); } } // end while over tables - } // end if @@ -433,14 +385,14 @@ if ($col_rs && PMA_DBI_num_rows($col_rs) > 0) { $foreign_field = FALSE; } $seen_key = FALSE; - foreach ($selectboxall AS $key => $value) { + foreach ($selectboxall as $value) { echo ' ' - . ''. "\n"; + echo '>' . htmlspecialchars($value) . ''. "\n"; } // end while // if the link defined in relationtable points to a foreign field @@ -474,14 +426,14 @@ if ($col_rs && PMA_DBI_num_rows($col_rs) > 0) { } $found_foreign_field = FALSE; - foreach ($selectboxall_innodb AS $key => $value) { + foreach ($selectboxall_innodb as $value) { echo ' ' - . ''. "\n"; + echo '>' . htmlspecialchars($value) . ''. "\n"; } // end while // we did not find the foreign field in the tables of current db, @@ -499,7 +451,7 @@ if ($col_rs && PMA_DBI_num_rows($col_rs) > 0) { 0) { .'' . "\n"; PMA_generate_dropdown('ON UPDATE', - 'on_update[' . htmlspecialchars($save_row[$i]['Field']) . ']', + 'on_update[' . $save_row[$i]['Field'] . ']', $options_array, isset($existrel_innodb[$myfield]['on_update']) ? $existrel_innodb[$myfield]['on_update']: ''); echo '' . "\n";