Hi Dave On Thu, Feb 21, 2019 at 8:29 PM Dave Page <dp...@pgadmin.org> wrote:
> Hi > > On Thu, Feb 21, 2019 at 12:40 PM Akshay Joshi < > akshay.jo...@enterprisedb.com> wrote: > >> Hi Hackers, >> >> Attached is the implementation of feature #2418 "add rollback and commit >> action buttons on Query Tool". I have added jasmine test cases, modified >> regression test. I have not added feature test as it is not stable and >> document is also not updated as we are going to update the new screenshots. >> >> Please review it. >> > > I found a few quirks: > > - The buttons disable themselves after a short delay when a long running > query is executed. Shouldn't we just disable them in > disable_tool_buttons()? > Fixed. We should not disable them in disable_tool_buttons() as behaviour is different and I don't want to add multiple if else in disable_tool_buttons(). > - The buttons are initially disabled, until a command is run. Shouldn't > they return to that state after a commit or rollback (whether from a button > press or typed SQL query)? > Not able to reproduce this issue. I have tried with button press and keyboard shortcut, it disabled the commit or rollback button. > - Please update the docs, even if you don't update the screenshot > (otherwise we'll forget). > Fixed. Attached is the modified patch. > > Thanks. > > -- > Dave Page > Blog: http://pgsnake.blogspot.com > Twitter: @pgsnake > > EnterpriseDB UK: http://www.enterprisedb.com > The Enterprise PostgreSQL Company > -- *Akshay Joshi* *Sr. Software Architect * *Phone: +91 20-3058-9517Mobile: +91 976-788-8246*
diff --git a/docs/en_US/query_tool.rst b/docs/en_US/query_tool.rst index d066270..bafbca3 100644 --- a/docs/en_US/query_tool.rst +++ b/docs/en_US/query_tool.rst @@ -49,99 +49,98 @@ icons may support functionality accessed via the :ref:`data editor <editgrid>`. Hover over an icon to display a tooltip that describes the icon's functionality: -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ -| Icon | Behavior | Shortcut | -+======================+===================================================================================================+=============+ -| *Open File* | Click the *Open File* icon to display a previously saved query in the SQL Editor. | | -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ -| *Save* | Click the *Save* icon to perform a quick-save of a previously saved query, or to access the | | -| | *Save* menu: | | -| | | | -| | * Select *Save* to save the selected content of the SQL Editor panel in a file. | | -| | | | -| | * Select *Save As* to open a new browser dialog and specify a new location to which to save the | | -| | selected content of the SQL Editor panel. | | -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ -| *Find* | Use the *Find* menu to search, replace, or navigate the code displayed in the SQL Editor: | | -| | | | -| | * Select *Find* to provide a search target, and search the SQL Editor contents. | Cmd+F | -| | | | -| | * Select *Find next* to locate the next occurrence of the search target. | Cmd+G | -| | | | -| | * Select *Find previous* to move to the last occurrence of the search target. | Cmd+Shift+G | -| | | | -| | * Select *Pesistent find* to identify all occurrences of the search target within the editor. | | -| | | | -| | * Select *Replace* to locate and replace (with prompting) individual occurrences of the target. | Cmd+Shift+F | -| | | | -| | * Select *Replace all* to locate and replace all occurrences of the target within the editor. | | -| | | | -| | * Select *Jump* to navigate to the next occurrence of the search target. | Alt+G | -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ -| *Copy* | Click the *Copy* icon to copy the content that is currently highlighted in the Data Output panel. | | -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ -| *Edit* | Use options on the *Edit* menu to access text editing tools; the options operate on the text | | -| | displayed in the SQL Editor panel: | | -| | | | -| | * Select *Indent Selection* to indent the currently selected text. | Tab | -| | | | -| | * Select *Unindent Selection* to remove indentation from the currently selected text. | Shift+Tab | -| | | | -| | * Select *Inline Comment Selection* to enclose any lines that contain the selection in | Cmd+/ | -| | SQL style comment notation. | | -| | | | -| | * Select *Inline Uncomment Selection* to remove SQL style comment notation from the | Cmd+. | -| | selected line. | | -| | | | -| | * Select *Block Comment* to enclose all lines that contain the selection in C style | Shift+Cmd+/ | -| | comment notation. This option acts as a toggle. | | -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ -| *Execute/Refresh* | Click the *Execute/Refresh* icon to either execute or refresh the query highlighted in the SQL | | -| | editor panel. Click the down arrow to access other execution options: | | -| | | | -| | * Select *Execute/Refresh* to invoke the SQL command and refresh the result set. | F5 | -| | | | -| | * Select *Explain* to view an explanation plan for the current query. The result of the | F7 | -| | EXPLAIN is displayed graphically on the *Explain* tab of the output panel, and in text | | -| | form on the *Data Output* tab. | | -| | | | -| | * Select *Explain analyze* to invoke an EXPLAIN ANALYZE command on the current query. | Shift+F7 | -| | | | -| | * Navigate through the *Explain Options* menu to select options for the EXPLAIN command: | | -| | | | -| | Select *Verbose* to display additional information regarding the query plan. | | -| | | | -| | Select *Costs* to include information on the estimated startup and total cost of each | | -| | plan node, as well as the estimated number of rows and the estimated width of each | | -| | row. | | -| | | | -| | Select *Buffers* to include information on buffer usage. | | -| | | | -| | Select *Timing* to include information about the startup time and the amount of time | | -| | spent in each node of the query. | | -| | | | -| | * Add a check next to *Auto-Rollback* to instruct the server to automatically roll back a | | -| | transaction if an error occurs during the transaction. | | -| | | | -| | * Add a check next to *Auto-Commit* to instruct the server to automatically commit each | | -| | transaction. Any changes made by the transaction will be visible to others, and | | -| | durable in the event of a crash. | | -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ -| *Stop* | Click the *Stop* icon to cancel the execution of the currently running query. | | -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ -| *Clear query window* | Use options on the *Clear* drop-down menu to erase display contents: | | -| | | | -| | * Select *Clear Query Window* to erase the content of the SQL Editor panel. | | -| | | | -| | | | -| | * Select *Explain analyze* to invoke an EXPLAIN ANALYZE command on the current query. | Shift+F7 | -| | | | -| | the SQL editor panel or the *History* tab. | | -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ -| *Download as CSV* | Click the *Download as CSV* icon to download the result set of the current query to a | F8 | -| | comma-separated list. You can specify the CSV settings through | | -| | *Preferences -> SQL Editor -> CSV output* dialogue. | | -+----------------------+---------------------------------------------------------------------------------------------------+-------------+ ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| Icon | Behavior | Shortcut | ++======================+===================================================================================================+================+ +| *Open File* | Click the *Open File* icon to display a previously saved query in the SQL Editor. | Accesskey + O | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Save* | Click the *Save* icon to perform a quick-save of a previously saved query, or to access the | Accesskey + S | +| | *Save* menu: | | +| | | | +| | * Select *Save* to save the selected content of the SQL Editor panel in a file. | | +| | | | +| | * Select *Save As* to open a new browser dialog and specify a new location to which to save the | | +| | selected content of the SQL Editor panel. | | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Find* | Use the *Find* menu to search, replace, or navigate the code displayed in the SQL Editor: | | +| | | | +| | * Select *Find* to provide a search target, and search the SQL Editor contents. | Cmd+F | +| | | | +| | * Select *Find next* to locate the next occurrence of the search target. | Cmd+G | +| | | | +| | * Select *Find previous* to move to the last occurrence of the search target. | Cmd+Shift+G | +| | | | +| | * Select *Pesistent find* to identify all occurrences of the search target within the editor. | | +| | | | +| | * Select *Replace* to locate and replace (with prompting) individual occurrences of the target. | Cmd+Shift+F | +| | | | +| | * Select *Replace all* to locate and replace all occurrences of the target within the editor. | | +| | | | +| | * Select *Jump* to navigate to the next occurrence of the search target. | Alt+G | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Copy* | Click the *Copy* icon to copy the content that is currently highlighted in the Data Output panel. | Accesskey + C | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Edit* | Use options on the *Edit* menu to access text editing tools; the options operate on the text | | +| | displayed in the SQL Editor panel: | | +| | | | +| | * Select *Indent Selection* to indent the currently selected text. | Tab | +| | | | +| | * Select *Unindent Selection* to remove indentation from the currently selected text. | Shift+Tab | +| | | | +| | * Select *Inline Comment Selection* to enclose any lines that contain the selection in | Cmd+/ | +| | SQL style comment notation. | | +| | | | +| | * Select *Inline Uncomment Selection* to remove SQL style comment notation from the | Cmd+. | +| | selected line. | | +| | | | +| | * Select *Block Comment* to enclose all lines that contain the selection in C style | Shift+Cmd+/ | +| | comment notation. This option acts as a toggle. | | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Stop* | Click the *Stop* icon to cancel the execution of the currently running query. | Accesskey + Q | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Execute/Refresh* | Click the *Execute/Refresh* icon to either execute or refresh the query highlighted in the SQL | F5 | +| | editor panel. Click the down arrow to access other execution options: | | +| | | | +| | * Add a check next to *Auto-Rollback* to instruct the server to automatically roll back a | | +| | transaction if an error occurs during the transaction. | | +| | | | +| | * Add a check next to *Auto-Commit* to instruct the server to automatically commit each | | +| | transaction. Any changes made by the transaction will be visible to others, and | | +| | durable in the event of a crash. | | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Explain* | Click the *Explain* icon to view an explanation plan for the current query. The result of the | F7 | +| | EXPLAIN is displayed graphically on the *Explain* tab of the output panel, and in text | | +| | form on the *Data Output* tab. | | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Explain analyze* | Click the *Explain analyze* icon to invoke an EXPLAIN ANALYZE command on the current query. | Shift+F7 | +| | | | +| | * Navigate through the *Explain Options* menu to select options for the EXPLAIN command: | | +| | | | +| | Select *Verbose* to display additional information regarding the query plan. | | +| | | | +| | Select *Costs* to include information on the estimated startup and total cost of each | | +| | plan node, as well as the estimated number of rows and the estimated width of each | | +| | row. | | +| | | | +| | Select *Buffers* to include information on buffer usage. | | +| | | | +| | Select *Timing* to include information about the startup time and the amount of time | | +| | spent in each node of the query. | | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Commit* | Click the *Commit* icon to commit the transaction. | Shift+CTRL+M | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Rollback* | Click the *Rollback* icon to rollback the transaction. | Shift+CTRL+R | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Clear* | Use options on the *Clear* drop-down menu to erase display contents: | Accesskey + L | +| | | | +| | * Select *Clear Query Window* to erase the content of the SQL Editor panel. | | +| | | | +| | * Select *Clear History* to erase the content of the *History* tab. | | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ +| *Download as CSV* | Click the *Download as CSV* icon to download the result set of the current query to a | F8 | +| | comma-separated list. You can specify the CSV settings through | | +| | *Preferences -> SQL Editor -> CSV output* dialogue. | | ++----------------------+---------------------------------------------------------------------------------------------------+----------------+ **The SQL Editor Panel** diff --git a/web/pgadmin/static/js/keyboard_shortcuts.js b/web/pgadmin/static/js/keyboard_shortcuts.js index a5c8e13..70aab91 100644 --- a/web/pgadmin/static/js/keyboard_shortcuts.js +++ b/web/pgadmin/static/js/keyboard_shortcuts.js @@ -181,6 +181,8 @@ function keyboardShortcutsQueryTool( let nextPanelKeys = sqlEditorController.preferences.move_next; let previousPanelKeys = sqlEditorController.preferences.move_previous; let toggleCaseKeys = sqlEditorController.preferences.toggle_case; + let commitKeys = sqlEditorController.preferences.commit_transaction; + let rollbackKeys = sqlEditorController.preferences.rollback_transaction; if (this.validateShortcutKeys(executeKeys, event)) { this._stopEventPropagation(event); @@ -197,6 +199,18 @@ function keyboardShortcutsQueryTool( } else if (this.validateShortcutKeys(toggleCaseKeys, event)) { this._stopEventPropagation(event); queryToolActions.toggleCaseOfSelectedText(sqlEditorController); + } else if (this.validateShortcutKeys(commitKeys, event)) { + // If transaction buttons are disabled then no need to execute commit. + if (!sqlEditorController.is_transaction_buttons_disabled) { + this._stopEventPropagation(event); + queryToolActions.executeCommit(sqlEditorController); + } + } else if (this.validateShortcutKeys(rollbackKeys, event)) { + // If transaction buttons are disabled then no need to execute rollback. + if (!sqlEditorController.is_transaction_buttons_disabled) { + this._stopEventPropagation(event); + queryToolActions.executeRollback(sqlEditorController); + } } else if (( (this.isMac() && event.metaKey) || (!this.isMac() && event.ctrlKey) diff --git a/web/pgadmin/static/js/sqleditor/execute_query.js b/web/pgadmin/static/js/sqleditor/execute_query.js index 5542177..28df00d 100644 --- a/web/pgadmin/static/js/sqleditor/execute_query.js +++ b/web/pgadmin/static/js/sqleditor/execute_query.js @@ -81,6 +81,12 @@ class ExecuteQuery { } else { self.loadingScreen.hide(); self.enableSQLEditorButtons(); + // Enable/Disable commit and rollback button. + if (result.data.data.transaction_status == 2 || result.data.data.transaction_status == 3) { + self.enableTransactionButtons(); + } else { + self.disableTransactionButtons(); + } self.sqlServerObject.update_msg_history(false, httpMessageData.data.result); if ('notifies' in httpMessageData.data) self.sqlServerObject.update_notifications(httpMessageData.data.notifies); @@ -114,6 +120,13 @@ class ExecuteQuery { }) ).then( (httpMessage) => { + // Enable/Disable commit and rollback button. + if (httpMessage.data.data.transaction_status == 2 || httpMessage.data.data.transaction_status == 3) { + self.enableTransactionButtons(); + } else { + self.disableTransactionButtons(); + } + if (ExecuteQuery.isQueryFinished(httpMessage)) { self.loadingScreen.setMessage('Loading data from the database server and rendering...'); @@ -183,6 +196,7 @@ class ExecuteQuery { this.sqlServerObject.rows_affected = 0; this.sqlServerObject._init_polling_flags(); this.disableSQLEditorButtons(); + this.disableTransactionButtons(); } static prepareAnalyzeSql(sqlStatement, analyzeSql) { @@ -246,6 +260,15 @@ class ExecuteQuery { this.sqlServerObject.disable_tool_buttons(true); } + enableTransactionButtons() { + this.sqlServerObject.disable_transaction_buttons(false); + } + + disableTransactionButtons() { + this.sqlServerObject.special_sql = undefined; + this.sqlServerObject.disable_transaction_buttons(true); + } + static wasConnectionLostToPythonServer(httpResponse) { return _.isUndefined(httpResponse) || _.isUndefined(httpResponse.data); } diff --git a/web/pgadmin/static/js/sqleditor/query_tool_actions.js b/web/pgadmin/static/js/sqleditor/query_tool_actions.js index f82ed9d..7739e9b 100644 --- a/web/pgadmin/static/js/sqleditor/query_tool_actions.js +++ b/web/pgadmin/static/js/sqleditor/query_tool_actions.js @@ -141,6 +141,18 @@ let queryToolActions = { codeMirrorObj.replaceSelection(selectedText.toUpperCase()); } }, + + executeCommit: function (sqlEditorController) { + var self = this; + sqlEditorController.special_sql = 'COMMIT;'; + self.executeQuery(sqlEditorController); + }, + + executeRollback: function (sqlEditorController) { + var self = this; + sqlEditorController.special_sql = 'ROLLBACK;'; + self.executeQuery(sqlEditorController); + }, }; module.exports = queryToolActions; diff --git a/web/pgadmin/static/js/sqleditor/query_tool_preferences.js b/web/pgadmin/static/js/sqleditor/query_tool_preferences.js index 5b63988..daeefad 100644 --- a/web/pgadmin/static/js/sqleditor/query_tool_preferences.js +++ b/web/pgadmin/static/js/sqleditor/query_tool_preferences.js @@ -97,6 +97,14 @@ function updateUIPreferences(sqlEditor) { .attr('title', shortcut_title('Download as CSV',preferences.download_csv)); + $el.find('#btn-commit') + .attr('title', + shortcut_title('Commit',preferences.commit_transaction)); + + $el.find('#btn-rollback') + .attr('title', + shortcut_title('Rollback',preferences.rollback_transaction)); + /* Set Auto-commit and auto-rollback on query editor */ if (preferences.auto_commit) { $el.find('.auto-commit').removeClass('visibility-hidden'); diff --git a/web/pgadmin/tools/datagrid/templates/datagrid/index.html b/web/pgadmin/tools/datagrid/templates/datagrid/index.html index 5dd0bdc..067cd7a 100644 --- a/web/pgadmin/tools/datagrid/templates/datagrid/index.html +++ b/web/pgadmin/tools/datagrid/templates/datagrid/index.html @@ -218,7 +218,7 @@ tabindex="0" disabled > <i class="fa fa-stop sql-icon-lg" aria-hidden="true"></i> </button> - <button id="btn-flash" data-test-selector="execute-refresh-button" type="button" class="btn btn-sm btn-secondary" style="width: 40px;" + <button id="btn-flash" data-test-selector="execute-refresh-button" type="button" class="btn btn-sm btn-secondary" style="width: 32px;" title="" tabindex="0"> <i class="fa fa-bolt sql-icon-lg" aria-hidden="true"></i> @@ -288,6 +288,19 @@ </ul> </div> <div class="btn-group mr-1" role="group" aria-label=""> + <button id="btn-commit" type="button" class="btn btn-sm btn-secondary" + title="" + accesskey="" + tabindex="0" disabled> + <i class="icon-commit sql-icon-lg" aria-hidden="true"></i> + </button> + <button id="btn-rollback" type="button" class="btn btn-sm btn-secondary" + title="" + tabindex="0" disabled> + <i class="icon-rollback sql-icon-lg" aria-hidden="true"></i> + </button> + </div> + <div class="btn-group mr-1" role="group" aria-label=""> <button id="btn-clear-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="" diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py index 51f8129..8d5f857 100644 --- a/web/pgadmin/tools/sqleditor/__init__.py +++ b/web/pgadmin/tools/sqleditor/__init__.py @@ -584,6 +584,7 @@ def poll(trans_id): result is not None and additional_messages: result = additional_messages + result + transaction_status = conn.transaction_status() return make_json_response( data={ 'status': status, 'result': result, @@ -598,7 +599,8 @@ def poll(trans_id): 'types': types, 'client_primary_key': client_primary_key, 'has_oids': has_oids, - 'oids': oids + 'oids': oids, + 'transaction_status': transaction_status, }, encoding=conn.python_encoding ) diff --git a/web/pgadmin/tools/sqleditor/static/css/sqleditor.css b/web/pgadmin/tools/sqleditor/static/css/sqleditor.css index 81e63c3..cac4f66 100644 --- a/web/pgadmin/tools/sqleditor/static/css/sqleditor.css +++ b/web/pgadmin/tools/sqleditor/static/css/sqleditor.css @@ -297,6 +297,26 @@ input.editor-checkbox:focus { background-image: url('../img/disconnect.svg'); } +.icon-commit, .icon-rollback { + display: inline-block; + align-content: center; + vertical-align: middle; + height: 18px; + width: 18px; + background-size: 22px !important; + background-repeat: no-repeat; + background-position-x: center; + background-position-y: center; +} + +.icon-commit { + background-image: url('../img/commit.svg') !important; +} + +.icon-rollback { + background-image: url('../img/rollback.svg') !important; +} + .ajs-body .warn-header { font-size: 13px; font-weight: bold; diff --git a/web/pgadmin/tools/sqleditor/static/img/commit.svg b/web/pgadmin/tools/sqleditor/static/img/commit.svg new file mode 100644 index 0000000..7fd36e8 --- /dev/null +++ b/web/pgadmin/tools/sqleditor/static/img/commit.svg @@ -0,0 +1 @@ +<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><defs><style>.cls-1{fill:#222222;}</style></defs><title>commit</title><path class="cls-1" d="M51.89,28.51a21.22,21.22,0,0,0-6.3-2.1,45.22,45.22,0,0,0-8.67-.78,45.12,45.12,0,0,0-8.66.78,21.22,21.22,0,0,0-6.3,2.1c-1.54.89-2.32,1.85-2.32,2.88v2.88c0,1,.78,2,2.32,2.88a20.92,20.92,0,0,0,6.3,2.11,46,46,0,0,0,8.66.77,46.07,46.07,0,0,0,8.67-.77,20.92,20.92,0,0,0,6.3-2.11q2.31-1.32,2.31-2.88V31.39Q54.2,29.85,51.89,28.51Z"/><path class="cls-1" d="M36.92,51.56a49.08,49.08,0,0,1-10-1,19.79,19.79,0,0,1-7.32-2.86v3.82c0,1,.78,2,2.32,2.88a20.92,20.92,0,0,0,6.3,2.11,46,46,0,0,0,8.66.77,46.07,46.07,0,0,0,8.67-.77,20.92,20.92,0,0,0,6.3-2.11q2.31-1.32,2.31-2.88V47.74a19.67,19.67,0,0,1-7.31,2.86A49.11,49.11,0,0,1,36.92,51.56Z"/><path class="cls-1" d="M36.92,42.92a49.08,49.08,0,0,1-10-1,19.79,19.79,0,0,1-7.32-2.86v3.82c0,1,.78,2,2.32,2.88a20.92,20.92,0,0,0,6.3,2.11,46,46,0,0,0,8.66.77,46.07,46.07,0,0,0,8.67-.77,20.92,20.92,0,0,0,6.3-2.11q2.31-1.32,2.31-2.88V39.1A19.67,19.67,0,0,1,46.89,42,49.11,49.11,0,0,1,36.92,42.92Z"/><path class="cls-1" d="M25.67,12.44a11.28,11.28,0,0,1,4.23.8,11.13,11.13,0,0,1,3.6,2.28l-3.08,3.1a1.29,1.29,0,0,0-.31,1.56,1.33,1.33,0,0,0,1.32.9H41.51a1.43,1.43,0,0,0,1-.43,1.4,1.4,0,0,0,.42-1V9.56a1.34,1.34,0,0,0-.9-1.33,1.28,1.28,0,0,0-1.55.31l-2.92,2.91a17.34,17.34,0,0,0-5.51-3.52A17,17,0,0,0,19,8.05a19.15,19.15,0,0,0-3,1.6h0c-.43.3-.85.61-1.25.94l-.4.34h0a16.91,16.91,0,0,0-4.49,6,.8.8,0,0,0,0,.53.65.65,0,0,0,.31.39L14,20a.82.82,0,0,0,.6.05.72.72,0,0,0,.42-.4,11.46,11.46,0,0,1,1.12-2.11h0l.39-.54.24-.3c.18-.22.37-.44.57-.65L17.4,16l.45-.44.09-.09c.16-.15.33-.29.5-.43l.27-.2.21-.16a11.84,11.84,0,0,1,2.29-1.28A11.12,11.12,0,0,1,25.67,12.44Z"/></svg> diff --git a/web/pgadmin/tools/sqleditor/static/img/rollback.svg b/web/pgadmin/tools/sqleditor/static/img/rollback.svg new file mode 100644 index 0000000..89713cd --- /dev/null +++ b/web/pgadmin/tools/sqleditor/static/img/rollback.svg @@ -0,0 +1 @@ +<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><defs><style>.cls-1{fill:#222222;}</style></defs><title>rollback</title><path class="cls-1" d="M53.89,28.51a21.22,21.22,0,0,0-6.3-2.1,45.22,45.22,0,0,0-8.67-.78,45.12,45.12,0,0,0-8.66.78,21.22,21.22,0,0,0-6.3,2.1c-1.54.89-2.32,1.85-2.32,2.88v2.88c0,1,.78,2,2.32,2.88a20.92,20.92,0,0,0,6.3,2.11,46,46,0,0,0,8.66.77,46.07,46.07,0,0,0,8.67-.77,20.92,20.92,0,0,0,6.3-2.11q2.31-1.32,2.31-2.88V31.39Q56.2,29.85,53.89,28.51Z"/><path class="cls-1" d="M38.92,51.56a49.08,49.08,0,0,1-10-1,19.79,19.79,0,0,1-7.32-2.86v3.82c0,1,.78,2,2.32,2.88a20.92,20.92,0,0,0,6.3,2.11,46,46,0,0,0,8.66.77,46.07,46.07,0,0,0,8.67-.77,20.92,20.92,0,0,0,6.3-2.11q2.31-1.32,2.31-2.88V47.74a19.67,19.67,0,0,1-7.31,2.86A49.11,49.11,0,0,1,38.92,51.56Z"/><path class="cls-1" d="M38.92,42.92a49.08,49.08,0,0,1-10-1,19.79,19.79,0,0,1-7.32-2.86v3.82c0,1,.78,2,2.32,2.88a20.92,20.92,0,0,0,6.3,2.11,46,46,0,0,0,8.66.77,46.07,46.07,0,0,0,8.67-.77,20.92,20.92,0,0,0,6.3-2.11q2.31-1.32,2.31-2.88V39.1A19.67,19.67,0,0,1,48.89,42,49.11,49.11,0,0,1,38.92,42.92Z"/><path class="cls-1" d="M25.08,12.44a11.28,11.28,0,0,0-4.23.8,11.13,11.13,0,0,0-3.6,2.28l3.08,3.1a1.29,1.29,0,0,1,.31,1.56,1.33,1.33,0,0,1-1.32.9H9.24a1.43,1.43,0,0,1-1-.43,1.4,1.4,0,0,1-.42-1V9.56a1.34,1.34,0,0,1,.9-1.33,1.28,1.28,0,0,1,1.55.31l2.92,2.91a17.34,17.34,0,0,1,5.51-3.52,17,17,0,0,1,13.1.12,19.15,19.15,0,0,1,3,1.6h0c.43.3.85.61,1.25.94l.4.34h0a16.91,16.91,0,0,1,4.49,6,.8.8,0,0,1,0,.53.65.65,0,0,1-.31.39L36.8,20a.82.82,0,0,1-.6.05.72.72,0,0,1-.42-.4,11.46,11.46,0,0,0-1.12-2.11h0q-.19-.28-.39-.54l-.24-.3c-.18-.22-.37-.44-.57-.65L33.35,16l-.45-.44-.09-.09c-.16-.15-.33-.29-.5-.43l-.27-.2-.21-.16a11.84,11.84,0,0,0-2.29-1.28A11.12,11.12,0,0,0,25.08,12.44Z"/></svg> diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js index edac426..b857d80 100644 --- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js +++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js @@ -124,6 +124,8 @@ define('tools.querytool', [ // Indentation options 'click #btn-indent-code': 'on_indent_code', 'click #btn-unindent-code': 'on_unindent_code', + 'click #btn-commit': 'on_commit_transaction', + 'click #btn-rollback': 'on_rollback_transaction', }, reflectPreferences: function() { @@ -1779,6 +1781,15 @@ define('tools.querytool', [ } } }, + // Callback function for the commit button click. + on_commit_transaction: function() { + queryToolActions.executeCommit(this.handler); + }, + + // Callback function for the rollback button click. + on_rollback_transaction: function() { + queryToolActions.executeRollback(this.handler); + }, }); /* Defining controller class for data grid, which actually @@ -3405,6 +3416,15 @@ define('tools.querytool', [ } }, + // This function is used to enable/disable commit/rollback buttons + disable_transaction_buttons: function(disabled) { + this.is_transaction_buttons_disabled = disabled; + if (this.is_query_tool) { + $('#btn-commit').prop('disabled', disabled); + $('#btn-rollback').prop('disabled', disabled); + } + }, + // This function will fetch the sql query from the text box // and execute the query. execute: function(explain_prefix, shouldReconnect=false) { @@ -3414,14 +3434,18 @@ define('tools.querytool', [ self.has_more_rows = false; self.fetching_rows = false; - /* If code is selected in the code mirror then execute - * the selected part else execute the complete code. - */ - var selected_code = self.gridView.query_tool_obj.getSelection(); - if (selected_code.length > 0) - sql = selected_code; - else - sql = self.gridView.query_tool_obj.getValue(); + if (!_.isUndefined(self.special_sql)) { + sql = self.special_sql; + } else { + /* If code is selected in the code mirror then execute + * the selected part else execute the complete code. + */ + var selected_code = self.gridView.query_tool_obj.getSelection(); + if (selected_code.length > 0) + sql = selected_code; + else + sql = self.gridView.query_tool_obj.getValue(); + } const executeQuery = new ExecuteQuery.ExecuteQuery(this, pgAdmin.Browser.UserManagement); executeQuery.execute(sql, explain_prefix, shouldReconnect); diff --git a/web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py b/web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py index 9e7cfcd..3be6842 100644 --- a/web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py +++ b/web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py @@ -571,3 +571,39 @@ def RegisterQueryToolPreferences(self): help_str=gettext('If set to True, Keywords will be displayed ' 'in upper case for auto completion.') ) + + self.preference.register( + 'keyboard_shortcuts', + 'commit_transaction', + gettext('Commit'), + 'keyboardshortcut', + { + 'alt': False, + 'shift': True, + 'control': True, + 'key': { + 'key_code': 77, + 'char': 'm' + } + }, + category_label=gettext('Keyboard shortcuts'), + fields=shortcut_fields + ) + + self.preference.register( + 'keyboard_shortcuts', + 'rollback_transaction', + gettext('Rollback'), + 'keyboardshortcut', + { + 'alt': False, + 'shift': True, + 'control': True, + 'key': { + 'key_code': 82, + 'char': 'r' + } + }, + category_label=gettext('Keyboard shortcuts'), + fields=shortcut_fields + ) diff --git a/web/pgadmin/tools/sqleditor/utils/start_running_query.py b/web/pgadmin/tools/sqleditor/utils/start_running_query.py index c3fa54b..200b0e0 100644 --- a/web/pgadmin/tools/sqleditor/utils/start_running_query.py +++ b/web/pgadmin/tools/sqleditor/utils/start_running_query.py @@ -48,6 +48,7 @@ class StartRunningQuery: can_edit = False can_filter = False notifies = None + trans_status = None if transaction_object is not None and session_obj is not None: # set fetched row count to 0 as we are executing query again. transaction_object.update_fetched_row_cnt(0) @@ -91,6 +92,7 @@ class StartRunningQuery: # Get the notifies notifies = conn.get_notifies() + trans_status = conn.transaction_status() else: status = False result = gettext( @@ -101,7 +103,8 @@ class StartRunningQuery: 'can_edit': can_edit, 'can_filter': can_filter, 'info_notifier_timeout': self.blueprint_object.info_notifier_timeout.get(), - 'notifies': notifies + 'notifies': notifies, + 'transaction_status': trans_status, } ) diff --git a/web/pgadmin/tools/sqleditor/utils/tests/test_start_running_query.py b/web/pgadmin/tools/sqleditor/utils/tests/test_start_running_query.py index 2734735..6aec9af 100644 --- a/web/pgadmin/tools/sqleditor/utils/tests/test_start_running_query.py +++ b/web/pgadmin/tools/sqleditor/utils/tests/test_start_running_query.py @@ -118,7 +118,8 @@ class StartRunningQueryTest(BaseTestGenerator): can_edit=False, can_filter=False, info_notifier_timeout=5, - notifies=None + notifies=None, + transaction_status=None ) ), expect_internal_server_error_called_with=None, @@ -278,7 +279,8 @@ class StartRunningQueryTest(BaseTestGenerator): can_edit=True, can_filter=True, info_notifier_timeout=5, - notifies=None + notifies=None, + transaction_status=None ) ), expect_internal_server_error_called_with=None, @@ -322,7 +324,8 @@ class StartRunningQueryTest(BaseTestGenerator): can_edit=True, can_filter=True, info_notifier_timeout=5, - notifies=None + notifies=None, + transaction_status=None ) ), expect_internal_server_error_called_with=None, @@ -366,7 +369,8 @@ class StartRunningQueryTest(BaseTestGenerator): can_edit=True, can_filter=True, info_notifier_timeout=5, - notifies=None + notifies=None, + transaction_status=None ) ), expect_internal_server_error_called_with=None, @@ -411,7 +415,8 @@ class StartRunningQueryTest(BaseTestGenerator): can_edit=True, can_filter=True, info_notifier_timeout=5, - notifies=None + notifies=None, + transaction_status=None ) ), expect_internal_server_error_called_with=None, @@ -517,9 +522,11 @@ class StartRunningQueryTest(BaseTestGenerator): execute_async=MagicMock(), execute_void=MagicMock(), get_notifies=MagicMock(), + transaction_status=MagicMock(), ) self.connection.connect.return_value = self.connection_connect_return self.connection.get_notifies.return_value = None + self.connection.transaction_status.return_value = None self.connection.execute_async.return_value = \ self.execute_async_return_value if self.manager_connection_exception is None: diff --git a/web/regression/javascript/sqleditor/call_render_after_poll_spec.js b/web/regression/javascript/sqleditor/call_render_after_poll_spec.js index 14b6fc1..d68f5ee 100644 --- a/web/regression/javascript/sqleditor/call_render_after_poll_spec.js +++ b/web/regression/javascript/sqleditor/call_render_after_poll_spec.js @@ -22,6 +22,7 @@ describe('#callRenderAfterPoll', () => { trigger: jasmine.createSpy('SQLEditor.trigger'), update_msg_history: jasmine.createSpy('SQLEditor.update_msg_history'), disable_tool_buttons: jasmine.createSpy('SQLEditor.disable_tool_buttons'), + disable_transaction_buttons: jasmine.createSpy('SQLEditor.disable_transaction_buttons'), query_start_time: new Date(), }; alertify = jasmine.createSpyObj('alertify', ['success']); diff --git a/web/regression/javascript/sqleditor/execute_query_spec.js b/web/regression/javascript/sqleditor/execute_query_spec.js index 71ca979..fb7ad9a 100644 --- a/web/regression/javascript/sqleditor/execute_query_spec.js +++ b/web/regression/javascript/sqleditor/execute_query_spec.js @@ -44,6 +44,7 @@ describe('ExecuteQuery', () => { 'initTransaction', 'handle_connection_lost', 'update_notifications', + 'disable_transaction_buttons', ]); sqlEditorMock.transId = 123; sqlEditorMock.rows_affected = 1000; @@ -112,6 +113,46 @@ describe('ExecuteQuery', () => { }); }); + describe('when query was successful but in transaction block', () => { + beforeEach(() => { + response = { + data: {status: 'Success', notifies: [{'pid': 100}], transaction_status: 2}, + }; + networkMock.onGet('/sqleditor/query_tool/poll/123').reply(200, response); + + executeQuery.poll(); + }); + + it('enable the transaction buttons', (done) => { + setTimeout( + () => { + expect(sqlEditorMock.disable_transaction_buttons) + .toHaveBeenCalledWith(false); + done(); + }, 0); + }); + }); + + describe('when query was successful but not in transaction block', () => { + beforeEach(() => { + response = { + data: {status: 'Success', notifies: [{'pid': 100}], transaction_status: 0}, + }; + networkMock.onGet('/sqleditor/query_tool/poll/123').reply(200, response); + + executeQuery.poll(); + }); + + it('disable the transaction buttons', (done) => { + setTimeout( + () => { + expect(sqlEditorMock.disable_transaction_buttons) + .toHaveBeenCalledWith(true); + done(); + }, 0); + }); + }); + describe('when query is still running', () => { context('when no additional information is returned', () => { beforeEach(() => { diff --git a/web/regression/javascript/sqleditor/keyboard_shortcuts_spec.js b/web/regression/javascript/sqleditor/keyboard_shortcuts_spec.js index 543ae37..d7e1856 100644 --- a/web/regression/javascript/sqleditor/keyboard_shortcuts_spec.js +++ b/web/regression/javascript/sqleditor/keyboard_shortcuts_spec.js @@ -93,6 +93,22 @@ describe('the keyboard shortcuts', () => { key_code: null, }, }, + commit_transaction: { + alt: false, + shift: true, + control: true, + key: { + key_code: 'm', + }, + }, + rollback_transaction: { + alt: false, + shift: true, + control: true, + key: { + key_code: 'r', + }, + }, }; queryToolActionsSpy = jasmine.createSpyObj(queryToolActions, [ @@ -103,6 +119,8 @@ describe('the keyboard shortcuts', () => { 'commentLineCode', 'uncommentLineCode', 'executeQuery', + 'executeCommit', + 'executeRollback', ]); }); @@ -521,6 +539,80 @@ describe('the keyboard shortcuts', () => { }); }); + describe('Shift+Ctrl+C', () => { + describe('when there is not a query already running', () => { + beforeEach(() => { + event.shiftKey = true; + event.which = 'm'; + event.altKey = false; + event.ctrlKey = true; + keyboardShortcuts.processEventQueryTool( + sqlEditorControllerSpy, queryToolActionsSpy, event + ); + }); + + it('should commit the transaction', () => { + expect(queryToolActionsSpy.executeCommit).toHaveBeenCalledWith(sqlEditorControllerSpy); + }); + + expectEventPropagationToStop(); + }); + + describe('when the query is already running', () => { + it('does nothing', () => { + event.shiftKey = true; + event.which = 'm'; + event.altKey = false; + event.ctrlKey = true; + + sqlEditorControllerSpy.isQueryRunning.and.returnValue(true); + + keyboardShortcuts.processEventQueryTool( + sqlEditorControllerSpy, queryToolActionsSpy, event + ); + + expect(queryToolActionsSpy.executeCommit).not.toHaveBeenCalled(); + }); + }); + }); + + describe('Shift+Ctrl+R', () => { + describe('when there is not a query already running', () => { + beforeEach(() => { + event.shiftKey = true; + event.which = 'r'; + event.altKey = false; + event.ctrlKey = true; + keyboardShortcuts.processEventQueryTool( + sqlEditorControllerSpy, queryToolActionsSpy, event + ); + }); + + it('should rollback the transaction', () => { + expect(queryToolActionsSpy.executeRollback).toHaveBeenCalledWith(sqlEditorControllerSpy); + }); + + expectEventPropagationToStop(); + }); + + describe('when the query is already running', () => { + it('does nothing', () => { + event.shiftKey = true; + event.which = 'r'; + event.altKey = false; + event.ctrlKey = true; + + sqlEditorControllerSpy.isQueryRunning.and.returnValue(true); + + keyboardShortcuts.processEventQueryTool( + sqlEditorControllerSpy, queryToolActionsSpy, event + ); + + expect(queryToolActionsSpy.executeRollback).not.toHaveBeenCalled(); + }); + }); + }); + function expectEventPropagationToStop() { describe('stops all event propogation', () => { diff --git a/web/regression/javascript/sqleditor/query_tool_actions_spec.js b/web/regression/javascript/sqleditor/query_tool_actions_spec.js index 7504b5d..9c18743 100644 --- a/web/regression/javascript/sqleditor/query_tool_actions_spec.js +++ b/web/regression/javascript/sqleditor/query_tool_actions_spec.js @@ -521,6 +521,32 @@ describe('queryToolActions', () => { }); }); + describe('executeCommit', () => { + describe('when commit action is being run from the query tool', () => { + beforeEach(() => { + setUpSpies('', ''); + }); + + it('calls the execute commit function', () => { + queryToolActions.executeCommit(sqlEditorController); + expect(sqlEditorController.special_sql).toEqual('COMMIT;'); + }); + }); + }); + + describe('executeRollback', () => { + describe('when rollback action is being run from the query tool', () => { + beforeEach(() => { + setUpSpies('', ''); + }); + + it('calls the execute rollback function', () => { + queryToolActions.executeRollback(sqlEditorController); + expect(sqlEditorController.special_sql).toEqual('ROLLBACK;'); + }); + }); + }); + function setUpSpies(selectedQueryString, entireQueryString) { getValueSpy = jasmine.createSpy('getValueSpy').and.returnValue(entireQueryString); getSelectionSpy = jasmine.createSpy('getSelectionSpy').and.returnValue(selectedQueryString);