From 99b9e8d83c31112998a2c0479739ce0029cf0f6e Mon Sep 17 00:00:00 2001 From: Ashutosh Dhundhara Date: Fri, 6 Jun 2014 23:01:21 +0530 Subject: [PATCH] RFE#1145: Preview SQL instead of executing it. Signed-off-by: Ashutosh Dhundhara --- js/functions.js | 64 ++++++++++++- js/messages.php | 3 + libraries/core.lib.php | 27 ++++++ libraries/insert_edit.lib.php | 4 +- libraries/structure.lib.php | 8 +- libraries/tbl_columns_definition_form.lib.php | 1 + libraries/tbl_indexes.lib.php | 5 + libraries/tbl_relation.lib.php | 95 ++++++++++++------- tbl_create.php | 5 + tbl_replace.php | 7 +- test/libraries/PMA_insert_edit_test.php | 10 +- themes/pmahomme/css/common.css.php | 6 +- 12 files changed, 195 insertions(+), 40 deletions(-) diff --git a/js/functions.js b/js/functions.js index f9d98d8193..116d67d282 100644 --- a/js/functions.js +++ b/js/functions.js @@ -53,7 +53,7 @@ $.ajaxPrefilter(function (options, originalOptions, jqXHR) { }); /** - * Show notices for ENUM columns; add/hide the default value + * Show notices for ENUM columns; add/hide the default value * */ function PMA_verifyColumnsProperties() @@ -2279,6 +2279,13 @@ AJAX.registerOnload('functions.js', function () { .submit(); } }); + + $('body') + .off('click', 'input.preview_sql') + .on('click', 'input.preview_sql', function () { + var $form = $(this).closest('form'); + PMA_previewSQL($form); + }); }); @@ -2989,6 +2996,11 @@ function indexEditorDialog(url, title, callback_success, callback_failure) } }); // end $.post() }; + button_options[PMA_messages.strPreviewSQL] = function () { + // Funciton for Previewing SQL + var $form = $('#index_frm'); + PMA_previewSQL($form); + }; button_options[PMA_messages.strCancel] = function () { $(this).dialog('close'); }; @@ -4164,3 +4176,53 @@ function checkNumberOfFields() { return true; } + +/** + * Requests SQL for previewing before executing. + * + * @param jQuery Object $form Form containing query data + * + * @return void + */ +function PMA_previewSQL($form) +{ + var form_url = $form.attr('action'); + var form_data = $form.serialize() + + '&do_save_data=1' + + '&preview_sql=1' + + '&ajax_request=1'; + $.ajax({ + type: 'POST', + url: form_url, + data: form_data, + success: function (response) { + if (response.success) { + var $dialog_content = $('
') + .append(response.sql_data); + var button_options = {}; + button_options[PMA_messages.strClose] = function () { + $(this).dialog('close'); + }; + var $response_dialog = $dialog_content.dialog({ + minWidth: 550, + maxHeight: 400, + modal: true, + buttons: button_options, + title: PMA_messages.strPreviewSQL, + close: function () { + $(this).remove(); + }, + open: function () { + // Pretty SQL printing. + PMA_highlightSQL($(this)); + } + }); + } else { + PMA_ajaxShowMessage(response.message); + } + }, + error: function () { + PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest); + } + }); +} \ No newline at end of file diff --git a/js/messages.php b/js/messages.php index 5c31c098f7..4a2b464243 100644 --- a/js/messages.php +++ b/js/messages.php @@ -54,6 +54,9 @@ $js_messages['strAddIndex'] = __('Add Index'); $js_messages['strEditIndex'] = __('Edit Index'); $js_messages['strAddToIndex'] = __('Add %s column(s) to index'); +/* For Preview SQL*/ +$js_messages['strPreviewSQL'] = __('Preview SQL'); + /* Charts */ /* l10n: Default label for the y-Axis of Charts */ $js_messages['strYValues'] = __('Y Values'); diff --git a/libraries/core.lib.php b/libraries/core.lib.php index f9972ae842..8587581439 100644 --- a/libraries/core.lib.php +++ b/libraries/core.lib.php @@ -905,4 +905,31 @@ function PMA_mimeDefaultFunction($buffer) return $buffer; } + +/** + * Displays SQL query before executing. + * + * @param array|string $query_data Array containing queries or query itself + * + * @return void + */ +function PMA_previewSQL($query_data) +{ + $retval = '
'; + if (is_array($query_data) && count($query_data) > 0) { + foreach ($query_data as $query) { + $retval .= PMA_Util::formatSql($query); + } + } else { + if (! empty($query_data)) { + $retval .= PMA_Util::formatSql($query_data); + } else { + $retval .= __('No change'); + } + } + $retval .= '
'; + $response = PMA_Response::getInstance(); + $response->addJSON('sql_data', $retval); + exit; +} ?> diff --git a/libraries/insert_edit.lib.php b/libraries/insert_edit.lib.php index cd5d872187..de6c7e252b 100644 --- a/libraries/insert_edit.lib.php +++ b/libraries/insert_edit.lib.php @@ -1601,8 +1601,10 @@ function PMA_getSumbitAndResetButtonForActionsPanel($tabindex, $tabindex_for_val . '' . '' - . '' + . '' . ''; } diff --git a/libraries/structure.lib.php b/libraries/structure.lib.php index 3eefcc5d87..d92a1fe776 100644 --- a/libraries/structure.lib.php +++ b/libraries/structure.lib.php @@ -2479,7 +2479,7 @@ function PMA_updateColumns($db, $table) $response = PMA_Response::getInstance(); - if (count($changes) > 0) { + if (count($changes) > 0 || isset($_REQUEST['preview_sql'])) { // Builds the primary keys statements and updates the table $key_query = ''; /** @@ -2504,6 +2504,12 @@ function PMA_updateColumns($db, $table) $sql_query = 'ALTER TABLE ' . PMA_Util::backquote($table) . ' '; $sql_query .= implode(', ', $changes) . $key_query; $sql_query .= ';'; + + // If there is a request for SQL previewing. + if (isset($_REQUEST['preview_sql'])) { + PMA_previewSQL(count($changes) > 0 ? $sql_query : ''); + } + $result = $GLOBALS['dbi']->tryQuery($sql_query); if ($result !== false) { diff --git a/libraries/tbl_columns_definition_form.lib.php b/libraries/tbl_columns_definition_form.lib.php index bbc8f83acc..cf6328e21a 100644 --- a/libraries/tbl_columns_definition_form.lib.php +++ b/libraries/tbl_columns_definition_form.lib.php @@ -138,6 +138,7 @@ function PMA_getHtmlForTableConfigurations() function PMA_getHtmlForFooter() { $html = '
' + . '' . '' . '
' . '
' diff --git a/libraries/tbl_indexes.lib.php b/libraries/tbl_indexes.lib.php index 04e09a1cdb..ae9a846244 100644 --- a/libraries/tbl_indexes.lib.php +++ b/libraries/tbl_indexes.lib.php @@ -50,6 +50,11 @@ function PMA_handleCreateOrEditIndex($db, $table, $index) $sql_query = PMA_getSqlQueryForIndexCreateOrEdit($db, $table, $index, $error); + // If there is a request for SQL previewing. + if (isset($_REQUEST['preview_sql'])) { + PMA_previewSQL($sql_query); + } + if (! $error) { $GLOBALS['dbi']->query($sql_query); $message = PMA_Message::success( diff --git a/libraries/tbl_relation.lib.php b/libraries/tbl_relation.lib.php index 113bb2e570..30d746accf 100644 --- a/libraries/tbl_relation.lib.php +++ b/libraries/tbl_relation.lib.php @@ -362,6 +362,7 @@ function PMA_getHtmlForCommonFormHeader($db, $table) function PMA_getHtmlForCommonFormFooter() { return '
' + . '' . '' . '
' . ''; @@ -877,15 +878,26 @@ function PMA_handleUpdatesForForeignKeys($destination_foreign_db, $destination_foreign_column, $options_array, $table, $existrel_foreign ) { $html_output = ''; + $preview_sql_data = ''; $display_query = ''; $seen_error = false; + $preview_sql = (isset($_REQUEST['preview_sql'])) ? true : false; foreach ($destination_foreign_db as $master_field_md5 => $foreign_db) { - $html_output .= PMA_handleUpdateForForeignKey( + list($html, $sql_data) = 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 + $existrel_foreign, $table, $seen_error, $display_query, $foreign_db, + $preview_sql ); + $html_output .= $html; + $preview_sql_data .= $sql_data; } // end foreach + + // If there is a request for SQL previewing. + if ($preview_sql) { + PMA_previewSQL($preview_sql_data); + } + if (! empty($display_query) && ! $seen_error) { $GLOBALS['display_query'] = $display_query; $html_output = PMA_Util::getMessage( @@ -910,14 +922,16 @@ function PMA_handleUpdatesForForeignKeys($destination_foreign_db, * @param bool &$seen_error whether seen error * @param string &$display_query display query * @param string $foreign_db foreign database + * @param bool $preview_sql preview sql before executing * - * @return string + * @return array */ 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 + $existrel_foreign, $table, &$seen_error, &$display_query, $foreign_db, $preview_sql ) { $html_output = ''; + $preview_sql_data = ''; $create = false; $drop = false; @@ -963,16 +977,21 @@ function PMA_handleUpdateForForeignKey($multi_edit_columns_name, $master_field_m $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; + if (! $preview_sql) { + $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; + } + } else { + $preview_sql_data .= $drop_query . "\n"; } } $tmp_error_create = false; @@ -984,26 +1003,30 @@ function PMA_handleUpdateForForeignKey($multi_edit_columns_name, $master_field_m $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 (! $preview_sql) { + $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); - $html_output .= $message->getDisplay(); - } else { - $html_output .= PMA_Util::mysqlDie( - $tmp_error_create, $create_query, false, '', false - ); + 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); + $html_output .= $message->getDisplay(); + } else { + $html_output .= PMA_Util::mysqlDie( + $tmp_error_create, $create_query, false, '', false + ); + } + $html_output .= PMA_Util::showMySQLDocu( + 'InnoDB_foreign_key_constraints' + ) . "\n"; } - $html_output .= PMA_Util::showMySQLDocu( - 'InnoDB_foreign_key_constraints' - ) . "\n"; + } else { + $preview_sql_data .= $create_query . "\n"; } // this is an alteration and the old constraint has been dropped @@ -1023,11 +1046,15 @@ function PMA_handleUpdateForForeignKey($multi_edit_columns_name, $master_field_m $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); + if (! $preview_sql) { + $display_query .= $sql_query_recreate . "\n"; + $GLOBALS['dbi']->tryQuery($sql_query_recreate); + } else { + $preview_sql_data .= $sql_query_recreate; + } } } - return $html_output; + return array($html_output, $preview_sql_data); } ?> diff --git a/tbl_create.php b/tbl_create.php index 1b5184c313..70b1488386 100644 --- a/tbl_create.php +++ b/tbl_create.php @@ -55,6 +55,11 @@ $action = 'tbl_create.php'; */ if (isset($_REQUEST['do_save_data'])) { $sql_query = PMA_getTableCreationQuery($db, $table); + + // If there is a request for SQL previewing. + if (isset($_REQUEST['preview_sql'])) { + PMA_previewSQL($sql_query); + } // Executes the query $result = $GLOBALS['dbi']->tryQuery($sql_query); diff --git a/tbl_replace.php b/tbl_replace.php index e7efa5abd9..fae9eb2cb8 100644 --- a/tbl_replace.php +++ b/tbl_replace.php @@ -244,7 +244,7 @@ unset($multi_edit_columns_name, $multi_edit_columns_prev, $multi_edit_funcs, // Builds the sql query if ($is_insert && count($value_sets) > 0) { $query = PMA_buildSqlQuery($is_insertignore, $query_fields, $value_sets); -} elseif (empty($query)) { +} elseif (empty($query) && ! isset($_REQUEST['preview_sql'])) { // No change -> move back to the calling script // // Note: logic passes here for inline edit @@ -255,6 +255,11 @@ if ($is_insert && count($value_sets) > 0) { } unset($multi_edit_colummns, $is_insertignore); +// If there is a request for SQL previewing. +if (isset($_REQUEST['preview_sql'])) { + PMA_previewSQL($query); +} + /** * Executes the sql query and get the result, then move back to the calling * page diff --git a/test/libraries/PMA_insert_edit_test.php b/test/libraries/PMA_insert_edit_test.php index 0647944ac6..fec2661e13 100644 --- a/test/libraries/PMA_insert_edit_test.php +++ b/test/libraries/PMA_insert_edit_test.php @@ -1646,11 +1646,19 @@ class PMA_InsertEditTest extends PHPUnit_Framework_TestCase $this->assertTag( PMA_getTagArray( - '' ), $result ); + + $this->assertTag( + PMA_getTagArray( + '' + ), + $result + ); } /** diff --git a/themes/pmahomme/css/common.css.php b/themes/pmahomme/css/common.css.php index 4ceb9d6f85..ba9249c248 100644 --- a/themes/pmahomme/css/common.css.php +++ b/themes/pmahomme/css/common.css.php @@ -262,11 +262,13 @@ select:hover { } input[type=submit], +input[type=button], button[type=submit]:not(.mult_submit) { font-weight: bold !important; } input[type=submit], +input[type=button], button[type=submit]:not(.mult_submit), input[type=reset], input[name=submit_reset], @@ -288,6 +290,7 @@ input.button { } input[type=submit]:hover, +input[type=button]:hover, button[type=submit]:not(.mult_submit):hover, input[type=reset]:hover, input[name=submit_reset]:hover, @@ -298,6 +301,7 @@ input.button:hover { } input[type=submit]:active, +input[type=button]:active, button[type=submit]:not(.mult_submit):active, input[type=reset]:active, input[name=submit_reset]:active, @@ -317,7 +321,7 @@ textarea.char { height: em; } -fieldset { +fieldset, .preview_sql { margin-top: 1em; border-radius: 4px 4px 0 0; -moz-border-radius: 4px 4px 0 0;