Hi, Please find patch to fix the below issues,
1) Debugger page layout RM#2512 2) To fix the issue when you user clicks on Stop button and gets connection lost error. RM#2511 @Dave, When we stop the debugger using pldbg_abort_target() function and try to start it again in the same connection, we are not able to do so because we do not get response from plugin(async query results shows busy status only), I think that is the reason why in pgAdmin3 we have disable all the buttons and release the connection if user clicks on stop button, For time being I have done the same in pgAdmin4 until we find the solution for this issue. Misc changes are for PEP-8. Please review. -- Regards, Murtuza Zabuawala EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company
diff --git a/web/pgadmin/tools/debugger/__init__.py b/web/pgadmin/tools/debugger/__init__.py index 8cebffc..35a0378 100644 --- a/web/pgadmin/tools/debugger/__init__.py +++ b/web/pgadmin/tools/debugger/__init__.py @@ -524,7 +524,7 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None): 'newBrowserTab': new_browser_tab}) -@blueprint.route('/close/<int:trans_id>', methods=["GET"]) +@blueprint.route('/close/<int:trans_id>', methods=["DELETE"]) def close(trans_id): """ close(trans_id) @@ -849,10 +849,16 @@ def execute_debugger_query(trans_id, query_type): template_path = 'debugger/sql/v2' if conn.connected(): - sql = render_template("/".join([template_path, query_type + ".sql"]), session_id=obj['session_id']) - # As the query type is continue or step_into or step_over then we may get result after some time so poll the - # result. We need to update the frame id variable when user move the next step for debugging. - if query_type == 'continue' or query_type == 'step_into' or query_type == 'step_over': + sql = render_template( + "/".join([template_path, query_type + ".sql"]), + session_id=obj['session_id'] + ) + # As the query type is continue or step_into or step_over then we + # may get result after some time so poll the result. + # We need to update the frame id variable when user move the next + # step for debugging. + if query_type == 'continue' or query_type == 'step_into' or \ + query_type == 'step_over': # We should set the frame_id to 0 when execution starts. if obj['frame_id'] != 0: session_obj = debugger_data[str(trans_id)] @@ -860,29 +866,30 @@ def execute_debugger_query(trans_id, query_type): update_session_debugger_transaction(trans_id, session_obj) status, result = conn.execute_async(sql) - return make_json_response(data={'status': status, 'result': result}) + return make_json_response( + data={'status': status, 'result': result} + ) elif query_type == 'abort_target': status, result = conn.execute_dict(sql) - - manager.release(did=obj['database_id'], conn_id=obj['conn_id']) - - # Delete the existing debugger data in session variable - del session['debuggerData'][str(trans_id)] - del session['functionData'][str(trans_id)] - if not status: return internal_server_error(errormsg=result) else: - return make_json_response(info=gettext('Target Aborted.'), data={'status': status, 'result': result}) + return make_json_response( + info=gettext('Debugging aborted successfully.'), + data={'status': 'Success', 'result': result} + ) else: status, result = conn.execute_dict(sql) if not status: return internal_server_error(errormsg=result) else: - status = False - result = gettext('Not connected to server or connection with the server has been closed.') + result = gettext('Not connected to server or connection ' + 'with the server has been closed.') + return internal_server_error(errormsg=result) - return make_json_response(data={'status': 'Success', 'result': result['rows']}) + return make_json_response( + data={'status': 'Success', 'result': result['rows']} + ) @blueprint.route('/messages/<int:trans_id>/', methods=["GET"]) @@ -915,9 +922,12 @@ def messages(trans_id): status, result = conn.poll() notify = conn.messages() if notify: - # In notice message we need to find "PLDBGBREAK" string to find the port number to attach. - # Notice message returned by the server is "NOTICE: PLDBGBREAK:7". - # From the above message we need to find out port number as "7" so below logic will find 7 as port number + # In notice message we need to find "PLDBGBREAK" string to find the + # port number to attach. + # Notice message returned by the server is + # "NOTICE: PLDBGBREAK:7". + # From the above message we need to find out port number + # as "7" so below logic will find 7 as port number # and attach listened to that port number offset = notify[0].find('PLDBGBREAK') str_len = len('PLDBGBREAK') @@ -935,11 +945,18 @@ def messages(trans_id): status = 'Busy' else: status = 'Busy' + + return make_json_response( + data={'status': status, 'result': port_number} + ) else: - status = 'NotConnected' - result = gettext('Not connected to server or connection with the server has been closed.') + result = gettext( + 'Not connected to server or connection with the ' + 'server has been closed.' + ) + return internal_server_error(errormsg=str(result)) + - return make_json_response(data={'status': status, 'result': port_number}) @blueprint.route('/start_execution/<int:trans_id>/<int:port_num>', methods=['GET']) @@ -1422,7 +1439,10 @@ def poll_end_execution_result(trans_id): if str(trans_id) not in debugger_data: return make_json_response( data={'status': 'NotConnected', - 'result': gettext('Not connected to server or connection with the server has been closed.')} + 'result': gettext( + 'Not connected to server or connection with the ' + 'server has been closed.') + } ) obj = debugger_data[str(trans_id)] @@ -1447,18 +1467,23 @@ def poll_end_execution_result(trans_id): else: statusmsg = additional_msgs - return make_json_response(success=1, info=gettext("Execution Completed."), - data={'status': status, 'status_message': statusmsg}) + return make_json_response( + success=1, info=gettext("Execution Completed."), + data={'status': status, 'status_message': statusmsg} + ) if result: if 'ERROR' in result: status = 'ERROR' - return make_json_response(info=gettext("Execution completed with error"), - data={'status': status, 'status_message': result}) + return make_json_response( + info=gettext("Execution completed with error"), + data={'status': status, 'status_message': result} + ) else: status = 'Success' additional_msgs = conn.messages() if len(additional_msgs) > 0: - additional_msgs = [msg.strip("\n") for msg in additional_msgs] + additional_msgs = [msg.strip("\n") + for msg in additional_msgs] additional_msgs = "\n".join(additional_msgs) if statusmsg: statusmsg = additional_msgs + "\n" + statusmsg @@ -1467,9 +1492,11 @@ def poll_end_execution_result(trans_id): columns, result = convert_data_to_dict(conn, result) - return make_json_response(success=1, info=gettext("Execution Completed."), - data={'status': status, 'result': result, - 'col_info': columns, 'status_message': statusmsg}) + return make_json_response( + success=1, info=gettext("Execution Completed."), + data={'status': status, 'result': result, + 'col_info': columns, 'status_message': statusmsg} + ) else: status = 'Busy' additional_msgs = conn.messages() @@ -1485,7 +1512,8 @@ def poll_end_execution_result(trans_id): }) else: status = 'NotConnected' - result = gettext('Not connected to server or connection with the server has been closed.') + result = gettext('Not connected to server or connection with the ' + 'server has been closed.') return make_json_response(data={'status': status, 'result': result}) diff --git a/web/pgadmin/tools/debugger/templates/debugger/direct.html b/web/pgadmin/tools/debugger/templates/debugger/direct.html index 3e7bf2b..0e96817 100644 --- a/web/pgadmin/tools/debugger/templates/debugger/direct.html +++ b/web/pgadmin/tools/debugger/templates/debugger/direct.html @@ -11,7 +11,7 @@ try { window.onbeforeunload = function(ev) { $.ajax({ url: "{{ url_for('debugger.index') }}close/{{ uniqueId }}", - method: 'GET' + method: 'DELETE' }); }; }, diff --git a/web/pgadmin/tools/debugger/templates/debugger/js/debugger.js b/web/pgadmin/tools/debugger/templates/debugger/js/debugger.js index 624ca80..9664bc9 100644 --- a/web/pgadmin/tools/debugger/templates/debugger/js/debugger.js +++ b/web/pgadmin/tools/debugger/templates/debugger/js/debugger.js @@ -269,7 +269,7 @@ define([ var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; $.ajax({ url: closeUrl, - method: 'GET' + method: 'DELETE' }); }); } @@ -366,7 +366,7 @@ define([ var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; $.ajax({ url: closeUrl, - method: 'GET' + method: 'DELETE' }); }); } diff --git a/web/pgadmin/tools/debugger/templates/debugger/js/direct.js b/web/pgadmin/tools/debugger/templates/debugger/js/direct.js index ba71acb..cbc3055 100644 --- a/web/pgadmin/tools/debugger/templates/debugger/js/direct.js +++ b/web/pgadmin/tools/debugger/templates/debugger/js/direct.js @@ -543,7 +543,10 @@ define([ //Set the alertify message to inform the user that execution is completed with error. var alertifyWrapper = new AlertifyWrapper(); - alertifyWrapper.error(res.info, 3); + + if(!pgTools.DirectDebug.is_user_aborted_debugging) { + alertifyWrapper.error(res.info, 3); + } // Update the message tab of the debugger if (res.data.status_message) { @@ -555,14 +558,21 @@ define([ // remove progress cursor $('.debugger-container').removeClass('show_progress'); - // Execution completed so disable the buttons other than "Continue/Start" button because user can still - // start the same execution again. + // Execution completed so disable the buttons other than + // "Continue/Start" button because user can still start the + // same execution again. self.enable('stop', false); self.enable('step_over', false); self.enable('step_into', false); self.enable('toggle_breakpoint', false); self.enable('clear_all_breakpoints', false); - self.enable('continue', true); + // If debugging is stopped by user then do not enable + // continue/restart button + if(!pgTools.DirectDebug.is_user_aborted_debugging) + { + self.enable('continue', true); + pgTools.DirectDebug.is_user_aborted_debugging = false; + } // Stop further pooling pgTools.DirectDebug.is_polling_required = false; @@ -600,6 +610,7 @@ define([ var restart_dbg = res.data.restart_debug ? 1 : 0; // Start pooling again + pgTools.DirectDebug.polling_timeout_idle = false; pgTools.DirectDebug.is_polling_required = true; self.poll_end_execution_result(trans_id); self.poll_result(trans_id); @@ -768,7 +779,7 @@ define([ self.enable('step_into', false); self.enable('toggle_breakpoint', false); self.enable('clear_all_breakpoints', false); - self.enable('continue', true); + self.enable('continue', false); // Make ajax call to listen the database message var baseUrl = "{{ url_for('debugger.index') }}" + "execute_query/" + trans_id + "/" + "abort_target"; @@ -781,14 +792,19 @@ define([ // Call function to create and update local variables .... pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background'); pgTools.DirectDebug.direct_execution_completed = true; + pgTools.DirectDebug.is_user_aborted_debugging = true; - //Set the alertify message to inform the user that execution is completed. - var alertifyWrapper = new AlertifyWrapper(); - alertifyWrapper.success(res.info, 3); + // Stop further pooling + pgTools.DirectDebug.is_polling_required = false; - //Disable the buttons other than continue button. If user wants to again then it should allow to debug again... - self.enable('continue', true); + // Restarting debugging in the same transaction do not work + // We will give same behaviour as pgAdmin3 and disable all buttons + self.enable('continue', false); + // Set the alertify message to inform the user that execution + // is completed. + var alertifyWrapper = new AlertifyWrapper(); + alertifyWrapper.success(res.info, 3); } else if (res.data.status === 'NotConnected') { Alertify.alert( @@ -1353,6 +1369,7 @@ define([ this.direct_execution_completed = false; this.polling_timeout_idle = false; this.debug_restarted = false; + this.is_user_aborted_debugging = false; this.is_polling_required = true; // Flag to stop unwanted ajax calls var docker = this.docker = new wcDocker( @@ -1495,7 +1512,7 @@ define([ intializePanels: function() { var self = this; this.registerPanel( - 'code', false, '100%', '100%', + 'code', false, '100%', '50%', function(panel) { // Create the parameters panel to display the arguments of the functions