diff --git a/libraries/tbl_relation.lib.php b/libraries/tbl_relation.lib.php index 1beed173d5..eb4b66261b 100644 --- a/libraries/tbl_relation.lib.php +++ b/libraries/tbl_relation.lib.php @@ -568,7 +568,7 @@ function PMA_getHtmlForForeignKey($save_row, $i, $existrel_foreign, $myfield, $d /** * Function to send html for table or column dropdown list * - * @retrun void + * @return void */ function PMA_sendHtmlForTableOrColumnDropdownList() { @@ -620,7 +620,7 @@ function PMA_sendHtmlForTableDropdownList() ); } else { $query = 'SHOW TABLES FROM ' - . PMA_Util::backquote( $_REQUEST['foreignDb']); + . PMA_Util::backquote($_REQUEST['foreignDb']); } $tables_rs = $GLOBALS['dbi']->query( $query, @@ -707,4 +707,283 @@ function PMA_getQueryForDisplayUpdate($disp, $display_field, $db, $table, return $upd_query; } + +/** + * Function to handle updates for internal relations + * + * @param string $destination_db destination database + * @param string $multi_edit_columns_name multi edit column name + * @param string $destination_table destination table + * @param string $destination_column destination column + * @param array $cfgRelation configuration relation + * @param string $db current database + * @param string $table current table + * @param array $existrel db, table, column + * + * @return void + */ +function PMA_handleUpdatesForInternalRelations($destination_db, + $multi_edit_columns_name, $destination_table, $destination_column, $cfgRelation, + $db, $table, $existrel +) { + foreach ($destination_db as $master_field_md5 => $foreign_db) { + $upd_query = PMA_getQueryForInternalRelationUpdate( + $multi_edit_columns_name, + $master_field_md5, $foreign_db, $destination_table, $destination_column, + $cfgRelation, $db, $table, isset($existrel) ? $existrel : null + ); + if ($upd_query) { + PMA_queryAsControlUser($upd_query); + } + } +} + +/** + * Function to get update query for updating internal relations + * + * @param string $multi_edit_columns_name multi edit column names + * @param string $master_field_md5 master field md5 + * @param string $foreign_db foreign database + * @param string $destination_table destination table + * @param string $destination_column destination column + * @param array $cfgRelation configuration relation + * @param string $db current database + * @param string $table current table + * @param array $existrel db, table, column + * + * @return string + */ +function PMA_getQueryForInternalRelationUpdate($multi_edit_columns_name, + $master_field_md5, $foreign_db, $destination_table, $destination_column, + $cfgRelation, $db, $table, $existrel +) { + $upd_query = false; + + // Map the fieldname's md5 back to its real name + $master_field = $multi_edit_columns_name[$master_field_md5]; + + $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']) + . '.' . PMA_Util::backquote($cfgRelation['relation']) + . '(master_db, master_table, master_field, foreign_db,' + . ' foreign_table, foreign_field)' + . ' values(' + . '\'' . PMA_Util::sqlAddSlashes($db) . '\', ' + . '\'' . PMA_Util::sqlAddSlashes($table) . '\', ' + . '\'' . PMA_Util::sqlAddSlashes($master_field) . '\', ' + . '\'' . PMA_Util::sqlAddSlashes($foreign_db) . '\', ' + . '\'' . PMA_Util::sqlAddSlashes($foreign_table) . '\',' + . '\'' . PMA_Util::sqlAddSlashes($foreign_field) . '\')'; + + } 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' + . ' foreign_db = \'' + . PMA_Util::sqlAddSlashes($foreign_db) . '\', ' + . ' foreign_table = \'' + . PMA_Util::sqlAddSlashes($foreign_table) . '\', ' + . ' foreign_field = \'' + . PMA_Util::sqlAddSlashes($foreign_field) . '\' ' + . ' WHERE master_db = \'' + . PMA_Util::sqlAddSlashes($db) . '\'' + . ' AND master_table = \'' + . PMA_Util::sqlAddSlashes($table) . '\'' + . ' AND master_field = \'' + . PMA_Util::sqlAddSlashes($master_field) . '\''; + } // end if... else.... + } elseif (isset($existrel[$master_field])) { + $upd_query = 'DELETE FROM ' + . PMA_Util::backquote($GLOBALS['cfgRelation']['db']) + . '.' . PMA_Util::backquote($cfgRelation['relation']) + . ' WHERE master_db = \'' . PMA_Util::sqlAddSlashes($db) . '\'' + . ' AND master_table = \'' . PMA_Util::sqlAddSlashes($table) . '\'' + . ' AND master_field = \'' . PMA_Util::sqlAddSlashes($master_field) + . '\''; + } // end if... else.... + + return $upd_query; +} + +/** + * Function to handle foreign key updates + * + * @param string $destination_foreign_db destination foreign database + * @param string $multi_edit_columns_name multi edit column names + * @param string $destination_foreign_table destination foreign table + * @param string $destination_foreign_column destination foreign column + * @param array $options_array options array + * @param string $table current table + * @param array $existrel_foreign db, table, column + * + * @return string + */ +function PMA_handleUpdatesForForeignKeys($destination_foreign_db, + $multi_edit_columns_name, $destination_foreign_table, + $destination_foreign_column, $options_array, $table, $existrel_foreign +) { + $html_output = ''; + $display_query = ''; + $seen_error = false; + foreach ($destination_foreign_db as $master_field_md5 => $foreign_db) { + $html_output .= PMA_handleUpdateForForeignKey( + $multi_edit_columns_name, $master_field_md5, + $destination_foreign_table, $destination_foreign_column, $options_array, + $existrel_foreign, $table, $seen_error, $display_query, $foreign_db + ); + } // end foreach + if (! empty($display_query) && ! $seen_error) { + $GLOBALS['display_query'] = $display_query; + $html_output = PMA_Util::getMessage( + __('Your SQL query has been executed successfully'), + null, 'success' + ); + } + + return $html_output; +} + +/** + * Function to handle update for a foreign key + * + * @param array $multi_edit_columns_name multu edit columns name + * @param string $master_field_md5 master field md5 + * @param string $destination_foreign_table destination foreign table + * @param string $destination_foreign_column destination foreign column + * @param array $options_array options array + * @param array $existrel_foreign db, table, column + * @param string $table current table + * @param bool &$seen_error whether seen error + * @param string &$display_query display query + * @param string $foreign_db foreign database + * + * @return string + */ +function PMA_handleUpdateForForeignKey($multi_edit_columns_name, $master_field_md5, + $destination_foreign_table, $destination_foreign_column, $options_array, + $existrel_foreign, $table, &$seen_error, &$display_query, $foreign_db +) { + $html_output = ''; + $create = false; + $drop = false; + + // Map the fieldname's md5 back to it's real name + $master_field = $multi_edit_columns_name[$master_field_md5]; + + $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])) { + $constraint_name = $existrel_foreign[$master_field]['constraint']; + $on_delete = ! empty( + $existrel_foreign[$master_field]['on_delete']) + ? $existrel_foreign[$master_field]['on_delete'] : 'RESTRICT'; + $on_update = ! empty( + $existrel_foreign[$master_field]['on_update']) + ? $existrel_foreign[$master_field]['on_update'] : 'RESTRICT'; + } + if (! isset($existrel_foreign[$master_field])) { + // no key defined for this field + $create = true; + } 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] != $constraint_name + || ($_REQUEST['on_delete'][$master_field_md5] != $on_delete) + || ($_REQUEST['on_update'][$master_field_md5] != $on_update) + ) { + // another foreign key is already defined for this field + // or an option has been changed for ON DELETE or ON UPDATE + $drop = true; + $create = true; + } // end if... else.... + } elseif (isset($existrel_foreign[$master_field])) { + $drop = true; + } // end if... else.... + + $tmp_error_drop = false; + if ($drop) { + $drop_query = PMA_getSQLToDropForeignKey( + $table, $existrel_foreign[$master_field]['constraint'] + ); + $display_query .= $drop_query . "\n"; + $GLOBALS['dbi']->tryQuery($drop_query); + $tmp_error_drop = $GLOBALS['dbi']->getError(); + + if (! empty($tmp_error_drop)) { + $seen_error = true; + $html_output .= PMA_Util::mysqlDie( + $tmp_error_drop, $drop_query, false, '', false + ); + return $html_output; + } + } + $tmp_error_create = false; + if ($create) { + $create_query = PMA_getSQLToCreateForeignKey( + $table, $master_field, $foreign_db, $foreign_table, $foreign_field, + $_REQUEST['constraint_name'][$master_field_md5], + $options_array[$_REQUEST['on_delete'][$master_field_md5]], + $options_array[$_REQUEST['on_update'][$master_field_md5]] + ); + + $display_query .= $create_query . "\n"; + $GLOBALS['dbi']->tryQuery($create_query); + $tmp_error_create = $GLOBALS['dbi']->getError(); + if (! empty($tmp_error_create)) { + $seen_error = true; + + if (substr($tmp_error_create, 1, 4) == '1005') { + $message = PMA_Message::error( + __('Error creating foreign key on %1$s (check data types)') + ); + $message->addParam($master_field); + $message->display(); + } else { + $html_output .= PMA_Util::mysqlDie( + $tmp_error_create, $create_query, false, '', false + ); + } + $html_output .= PMA_Util::showMySQLDocu( + 'InnoDB_foreign_key_constraints' + ) . "\n"; + } + + // this is an alteration and the old constraint has been dropped + // without creation of a new one + if ($drop && $create && empty($tmp_error_drop) + && ! empty($tmp_error_create) + ) { + // a rollback may be better here + $sql_query_recreate = '# Restoring the dropped constraint...' . "\n"; + $sql_query_recreate .= PMA_getSQLToCreateForeignKey( + $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']] + ); + $display_query .= $sql_query_recreate . "\n"; + $GLOBALS['dbi']->tryQuery($sql_query_recreate); + } + } + + return $html_output; +} ?> diff --git a/tbl_relation.php b/tbl_relation.php index a8a58defcc..2dc55d9ad8 100644 --- a/tbl_relation.php +++ b/tbl_relation.php @@ -40,9 +40,6 @@ $scripts->addFile('indexes.js'); * Sets globals from $_POST */ $post_params = array( - 'destination_db', - 'destination_table', - 'destination_column', 'destination_foreign_db', 'destination_foreign_table', 'destination_foreign_column', @@ -93,192 +90,33 @@ $multi_edit_columns_name = isset($_REQUEST['fields_name']) ? $_REQUEST['fields_name'] : null; -$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_db) && $cfgRelation['relwork']) { - - 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]; - - $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']) - . '.' . PMA_Util::backquote($cfgRelation['relation']) - . '(master_db, master_table, master_field, foreign_db,' - . ' foreign_table, foreign_field)' - . ' values(' - . '\'' . PMA_Util::sqlAddSlashes($db) . '\', ' - . '\'' . PMA_Util::sqlAddSlashes($table) . '\', ' - . '\'' . PMA_Util::sqlAddSlashes($master_field) . '\', ' - . '\'' . PMA_Util::sqlAddSlashes($foreign_db) . '\', ' - . '\'' . PMA_Util::sqlAddSlashes($foreign_table) . '\',' - . '\'' . PMA_Util::sqlAddSlashes($foreign_field) . '\')'; - - } 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' - . ' foreign_db = \'' - . PMA_Util::sqlAddSlashes($foreign_db) . '\', ' - . ' foreign_table = \'' - . PMA_Util::sqlAddSlashes($foreign_table) . '\', ' - . ' foreign_field = \'' - . PMA_Util::sqlAddSlashes($foreign_field) . '\' ' - . ' WHERE master_db = \'' - . PMA_Util::sqlAddSlashes($db) . '\'' - . ' AND master_table = \'' - . PMA_Util::sqlAddSlashes($table) . '\'' - . ' AND master_field = \'' - . PMA_Util::sqlAddSlashes($master_field) . '\''; - } // end if... else.... - } elseif (isset($existrel[$master_field])) { - $upd_query = 'DELETE FROM ' - . PMA_Util::backquote($GLOBALS['cfgRelation']['db']) - . '.' . PMA_Util::backquote($cfgRelation['relation']) - . ' WHERE master_db = \'' . PMA_Util::sqlAddSlashes($db) . '\'' - . ' AND master_table = \'' . PMA_Util::sqlAddSlashes($table) . '\'' - . ' AND master_field = \'' . PMA_Util::sqlAddSlashes($master_field) - . '\''; - } // end if... else.... - if ($upd_query) { - PMA_queryAsControlUser($upd_query); - } - } // end while +if (isset($_POST['destination_db']) && $cfgRelation['relwork']) { + PMA_handleUpdatesForInternalRelations( + $_POST['destination_db'], $multi_edit_columns_name, + $_POST['destination_table'], + $_POST['destination_column'], $cfgRelation, $db, $table, + isset($existrel) ? $existrel : null + ); } // end if (updates for internal relations) +$html_output = ''; + // u p d a t e s f o r f o r e i g n k e y s // (for now, one index name only; we keep the definitions if the // foreign db is not the same) - if (isset($destination_foreign_db)) { - $display_query = ''; - $seen_error = false; - 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]; - - $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; - } 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')) - ) { - // another foreign key is already defined for this field - // or an option has been changed for ON DELETE or ON UPDATE - $drop = true; - $create = true; - } // end if... else.... - } elseif (isset($existrel_foreign[$master_field])) { - $drop = true; - } // end if... else.... - - $tmp_error_drop = false; - if ($drop) { - $drop_query = PMA_getSQLToDropForeignKey( - $table, $existrel_foreign[$master_field]['constraint'] - ); - $display_query .= $drop_query . "\n"; - $GLOBALS['dbi']->tryQuery($drop_query); - $tmp_error_drop = $GLOBALS['dbi']->getError(); - - if (! empty($tmp_error_drop)) { - $seen_error = true; - $html_output .= PMA_Util::mysqlDie( - $tmp_error_drop, $drop_query, false, '', false - ); - continue; - } - } - $tmp_error_create = false; - if ($create) { - $create_query = PMA_getSQLToCreateForeignKey( - $table, $master_field, $foreign_db, $foreign_table, $foreign_field, - $_REQUEST['constraint_name'][$master_field_md5], - $options_array[$_REQUEST['on_delete'][$master_field_md5]], - $options_array[$_REQUEST['on_update'][$master_field_md5]] - ); - - $display_query .= $create_query . "\n"; - $GLOBALS['dbi']->tryQuery($create_query); - $tmp_error_create = $GLOBALS['dbi']->getError(); - if (! empty($tmp_error_create)) { - $seen_error = true; - - if (substr($tmp_error_create, 1, 4) == '1005') { - $message = PMA_Message::error( - __('Error creating foreign key on %1$s (check data types)') - ); - $message->addParam($master_field); - $message->display(); - } else { - $html_output .= PMA_Util::mysqlDie( - $tmp_error_create, $create_query, false, '', false - ); - } - $html_output .= PMA_Util::showMySQLDocu( - 'InnoDB_foreign_key_constraints' - ) . "\n"; - } - - // this is an alteration and the old constraint has been dropped - // without creation of a new one - if ($drop && $create && empty($tmp_error_drop) - && ! empty($tmp_error_create) - ) { - // a rollback may be better here - $sql_query_recreate = '# Restoring the dropped constraint...' . "\n"; - $sql_query_recreate .= PMA_getSQLToCreateForeignKey( - $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']] - ); - $display_query .= $sql_query_recreate . "\n"; - $GLOBALS['dbi']->tryQuery($sql_query_recreate); - } - } - } // end foreach - if (! empty($display_query) && ! $seen_error) { - $html_output .= PMA_Util::getMessage( - __('Your SQL query has been executed successfully'), - null, 'success' - ); - } + $html_output .= PMA_handleUpdatesForForeignKeys( + $destination_foreign_db, + $multi_edit_columns_name, $destination_foreign_table, + $destination_foreign_column, $options_array, $table, + isset($existrel_foreign) ? $existrel_foreign : null + ); } // end if isset($destination_foreign) // 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)) { PMA_handleUpdateForDisplayField( $disp, $display_field, $db, $table, $cfgRelation @@ -286,7 +124,7 @@ if ($cfgRelation['displaywork'] && isset($display_field)) { } // end if // If we did an update, refresh our data -if (isset($destination_db) && $cfgRelation['relwork']) { +if (isset($_POST['destination_db']) && $cfgRelation['relwork']) { $existrel = PMA_getForeigners($db, $table, '', 'internal'); } if (isset($destination_foreign_db)