Hi Dave,

Please find updated patch where we are notifying user about connection
reset.

-- 
*Harshal Dhumal*
*Sr. Software Engineer*

EnterpriseDB India: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

On Mon, Jan 8, 2018 at 7:39 PM, Harshal Dhumal <
[email protected]> wrote:

> On Mon, Jan 8, 2018 at 7:26 PM, Dave Page <[email protected]> wrote:
>
>>
>>
>> On Mon, Jan 8, 2018 at 1:18 PM, Harshal Dhumal <
>> [email protected]> wrote:
>>
>>>
>>> On Mon, Jan 8, 2018 at 6:11 PM, Dave Page <[email protected]> wrote:
>>>
>>>>
>>>>
>>>> On Mon, Jan 8, 2018 at 12:37 PM, Harshal Dhumal <
>>>> [email protected]> wrote:
>>>>
>>>>> On Mon, Jan 8, 2018 at 5:15 PM, Dave Page <[email protected]> wrote:
>>>>>
>>>>>> HI
>>>>>>
>>>>>> On Mon, Jan 8, 2018 at 11:41 AM, Harshal Dhumal <
>>>>>> [email protected]> wrote:
>>>>>>
>>>>>>> On Mon, Jan 8, 2018 at 4:34 PM, Dave Page <[email protected]> wrote:
>>>>>>>
>>>>>>>> Hi
>>>>>>>>
>>>>>>>> On Fri, Jan 5, 2018 at 7:50 AM, Harshal Dhumal <
>>>>>>>> [email protected]> wrote:
>>>>>>>>
>>>>>>>>> Further details:
>>>>>>>>>
>>>>>>>>> 1. If session is expired and user performs any action from
>>>>>>>>> sqleditor that makes ajax call
>>>>>>>>> then in ajax error call back user can check and handle login
>>>>>>>>> related error using code snippet.
>>>>>>>>>
>>>>>>>>> if (pgAdmin.Browser.UserManagement.is_pga_login_required(xhr)) {
>>>>>>>>>   return pgAdmin.Browser.UserManagement.pga_login();
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> Where is xhr is standard xhr or jqxhr object.
>>>>>>>>>
>>>>>>>>> 2. Similarly for connection lost (only maintenance db connection
>>>>>>>>> as we can recover or reconnect other
>>>>>>>>> connections if maintenance db connection is alive). It will
>>>>>>>>> attempt to create/reconnect connection without
>>>>>>>>> asking password (to handle passwordless connection, or saveed
>>>>>>>>> password  or password from pgpass file)
>>>>>>>>> If connection to database still fails then it'll prompt for
>>>>>>>>> password.
>>>>>>>>>
>>>>>>>>> Code snippet:
>>>>>>>>> SqlEditorController.handle_connection_lost();
>>>>>>>>>  once connection lost is detected one can call
>>>>>>>>> handle_connection_lost() to reconnect.
>>>>>>>>>
>>>>>>>>> 3. We maintain some additional data in session to maintain
>>>>>>>>> affinity between
>>>>>>>>> each sqleditor/datagrid instance to backend database connection.
>>>>>>>>> However if session expires and user
>>>>>>>>> re-loggins then we need to first restore affinity between
>>>>>>>>> sqleditor to backend database before we can start
>>>>>>>>> using query tool.
>>>>>>>>>
>>>>>>>>> Code snippet:
>>>>>>>>>
>>>>>>>>> if(is_new_transaction_required(xhr)) {
>>>>>>>>>   SqlEditorController.init_transaction();
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> (note: I haven't looked at the code yet)
>>>>>>>>
>>>>>>>> How does this handle re-establishment of the connection
>>>>>>>> mid-transaction, or, if the user has modified any session variables?
>>>>>>>>
>>>>>>>> ServeManager and Connection Manager are written in a such way that
>>>>>>> if any connection is lost except maintenance db connection
>>>>>>> then we can re-connect or create new connection without prompting
>>>>>>> for database password and if maintenance db connection is lost
>>>>>>> then It prompts for password.
>>>>>>>
>>>>>>
>>>>>> Right.
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> Regarding session variables as long as flask session is not expired
>>>>>>> we uses same session variables. But in case of user logout (due to
>>>>>>> flask session expire) we create new transaction id and sets new
>>>>>>> session variables for that particular Sql editor /datagrid instance.
>>>>>>>
>>>>>>
>>>>>> I mean DB session variables (and related things). For example, if the
>>>>>> user executed queries such as the following, then they absolutely need to
>>>>>> know if the session got reset:
>>>>>>
>>>>>
>>>>> Ok.
>>>>> Then in this case can we notify user about the same. That we're unable
>>>>> to restore old database connection and created new one and therefore
>>>>> any DB session variables were set/modified (like SET
>>>>> CLIENT_ENCODING..., SET DATESTYLE...) are lost (or similar message).
>>>>>
>>>>>
>>>>>
>>>>>> CREATE TEMPORARY TABLE ....
>>>>>> SET ROLE ...
>>>>>> SET [various other options]
>>>>>>
>>>>>> If the user has done any of those things (or similar things that I
>>>>>> haven't thought of), then we cannot just blindly reset the database
>>>>>> connection.
>>>>>>
>>>>>
>>>>> We only create new connection if flask session was expired as we lost
>>>>> transaction id associated with Sql editor/datagrid and therefore unique
>>>>> connection id
>>>>> given to connection which was associated to Sql editor/datagrid. In
>>>>> this case we can notify about same (as stated above).
>>>>>
>>>>
>>>> If it's only the flask session we're resetting, not the database
>>>> connection, we won't need to warn the user will we?
>>>>
>>>
>>> The problem here is that if flask session is reset then we lose the
>>> information about which connection was associate with which query
>>> tool/datagrid.
>>>
>>> lets say If user have opened 3 query tools with same database therefore
>>> we'll have 3 separate connections
>>> (each will have unique connection id). Now this information that which
>>> connection is associate with which query
>>> tool is lost and also unique connection id. So there is no way that we
>>> can get that connection
>>> from connection manager ( *manager.connection(did=<some did>,
>>> conn_id=<unique connection id>)* ).
>>>
>>> So even database connection was not lost and only flask session was
>>> reset we need to create new connection. So I think we'll need to warn user.
>>>
>>
>> Agreed... and ensure the database connection is fully reset.
>>
>>
>>>
>>> Also If we save connection id to client side (in browser in JS) still we
>>> won't be able to get same connection
>>> even though we know connection id in case of flask session reset. As for
>>> each logged in user (pgAdmin user)
>>> but for same database server we create separate ServerManager (and
>>> therefore separate connection pool)
>>> and flask session reset is same as if same user is logged in from
>>> another browser.
>>>
>>>
>>>>
>>>> But... what if the database connection has also been lost in the
>>>> meantime. Would we handle that?
>>>>
>>> We create new connection irrespective of old connection state if flask
>>> session was reset as explained above.
>>>
>>
>> OK.
>>
>> So... we need to always warn the user that the connection has been reset,
>> so they know if they've lost previous GUC changes or temp tables etc, and
>> conversely, we need to reset the database connection to ensure thatGUC
>> changes or temp tables don't end up getting re-associated with the wrong
>> session. Sound right?
>>
>> Yes
>
>
>> I assume updates to the patch are required?
>>
> Yes. I'll send updated one.
>
>
>>
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>
>
diff --git a/web/pgadmin/__init__.py b/web/pgadmin/__init__.py
index 4a16ea1..0020469 100644
--- a/web/pgadmin/__init__.py
+++ b/web/pgadmin/__init__.py
@@ -25,7 +25,7 @@ from flask_paranoid import Paranoid
 
 from pgadmin.utils import PgAdminModule, driver
 from pgadmin.utils.versioned_template_loader import VersionedTemplateLoader
-from pgadmin.utils.session import create_session_interface
+from pgadmin.utils.session import create_session_interface, pga_unauthorised
 from werkzeug.local import LocalProxy
 from werkzeug.utils import find_modules
 
@@ -344,6 +344,9 @@ def create_app(app_name=None):
 
     security.init_app(app, user_datastore)
 
+    # register custom unauthorised handler.
+    app.login_manager.unauthorized_handler(pga_unauthorised)
+
     app.session_interface = create_session_interface(app)
 
     # Make the Session more secure against XSS & CSRF when running in web mode
diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py
index b2cca09..cad2dd8 100644
--- a/web/pgadmin/browser/server_groups/servers/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/__init__.py
@@ -202,6 +202,9 @@ class ServerModule(sg.ServerGroupPluginModule):
         """
         ServerType.register_preferences()
 
+    def get_exposed_url_endpoints(self):
+        return ['NODE-server.connect_id']
+
 
 class ServerMenuItem(MenuItem):
     def __init__(self, **kwargs):
diff --git a/web/pgadmin/tools/datagrid/__init__.py b/web/pgadmin/tools/datagrid/__init__.py
index 726a0ff..036d24a 100644
--- a/web/pgadmin/tools/datagrid/__init__.py
+++ b/web/pgadmin/tools/datagrid/__init__.py
@@ -17,7 +17,6 @@ import random
 from flask import Response, url_for, session, request, make_response
 from werkzeug.useragents import UserAgent
 from flask import current_app as app
-from flask_babel import gettext
 from flask_security import login_required
 from pgadmin.tools.sqleditor.command import *
 from pgadmin.utils import PgAdminModule
@@ -27,6 +26,9 @@ from pgadmin.utils.ajax import make_json_response, bad_request, \
 from config import PG_DEFAULT_DRIVER
 from pgadmin.utils.preferences import Preferences
 from pgadmin.model import Server
+from pgadmin.utils.driver import get_driver
+from pgadmin.utils.exception import ConnectionLost
+
 
 class DataGridModule(PgAdminModule):
     """
@@ -90,11 +92,11 @@ def show_filter():
 
 
 @blueprint.route(
-    '/initialize/datagrid/<int:cmd_type>/<obj_type>/<int:sid>/<int:did>/<int:obj_id>',
+    '/initialize/datagrid/<int:cmd_type>/<obj_type>/<int:sgid>/<int:sid>/<int:did>/<int:obj_id>',
     methods=["PUT", "POST"], endpoint="initialize_datagrid"
 )
 @login_required
-def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id):
+def initialize_datagrid(cmd_type, obj_type, sgid, sid, did, obj_id):
     """
     This method is responsible for creating an asynchronous connection.
     After creating the connection it will instantiate and initialize
@@ -104,6 +106,7 @@ def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id):
     Args:
         cmd_type: Contains value for which menu item is clicked.
         obj_type: Contains type of selected object for which data grid to be render
+        sgid: Server group Id
         sid: Server Id
         did: Database Id
         obj_id: Id of currently selected object
@@ -118,15 +121,26 @@ def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id):
     conn_id = str(random.randint(1, 9999999))
     try:
         manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
+        # default_conn is same connection which is created when user connect to
+        # database from tree
+        default_conn = manager.connection(did=did)
         conn = manager.connection(did=did, conn_id=conn_id,
                                   use_binary_placeholder=True,
                                   array_to_string=True)
+    except ConnectionLost as e:
+        raise
     except Exception as e:
+        app.logger.error(e)
         return internal_server_error(errormsg=str(e))
 
-    # Connect the Server
+    status, msg = default_conn.connect()
+    if not status:
+        app.logger.error(msg)
+        return internal_server_error(errormsg=str(msg))
+
     status, msg = conn.connect()
     if not status:
+        app.logger.error(msg)
         return internal_server_error(errormsg=str(msg))
 
     try:
@@ -135,10 +149,13 @@ def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id):
             obj_type = 'table'
 
         # Get the object as per the object type
-        command_obj = ObjectRegistry.get_object(obj_type, conn_id=conn_id, sid=sid,
-                                                did=did, obj_id=obj_id, cmd_type=cmd_type,
+        command_obj = ObjectRegistry.get_object(obj_type, conn_id=conn_id,
+                                                sgid=sgid, sid=sid, did=did,
+                                                obj_id=obj_id,
+                                                cmd_type=cmd_type,
                                                 sql_filter=filter_sql)
     except Exception as e:
+        app.logger.error(e)
         return internal_server_error(errormsg=str(e))
 
     # Create a unique id for the transaction
@@ -160,9 +177,11 @@ def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id):
 
     pref = Preferences.module('sqleditor')
     new_browser_tab = pref.preference('new_browser_tab').get()
-
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
     return make_json_response(data={'gridTransId': trans_id,
-                                    'newBrowserTab': new_browser_tab})
+                                    'newBrowserTab': new_browser_tab,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route(
@@ -217,11 +236,6 @@ def panel(trans_id, is_query_tool, editor_title):
     else:
         new_browser_tab = 'false'
 
-    if is_query_tool == 'true':
-        prompt_save_changes = pref.preference('prompt_save_query_changes').get()
-    else:
-        prompt_save_changes = pref.preference('prompt_save_data_changes').get()
-
     # Fetch the server details
     #
     bgcolor = None
@@ -239,6 +253,21 @@ def panel(trans_id, is_query_tool, editor_title):
                 bgcolor = s.bgcolor
             fgcolor = s.fgcolor or 'black'
 
+    url_params = dict()
+    if is_query_tool == 'true':
+        prompt_save_changes = pref.preference('prompt_save_query_changes').get()
+        url_params['sgid'] = trans_obj.sgid
+        url_params['sid'] = trans_obj.sid
+        url_params['did'] = trans_obj.did
+    else:
+        prompt_save_changes = pref.preference('prompt_save_data_changes').get()
+        url_params['cmd_type'] = trans_obj.cmd_type
+        url_params['obj_type'] = trans_obj.object_type
+        url_params['sgid'] = trans_obj.sgid
+        url_params['sid'] = trans_obj.sid
+        url_params['did'] = trans_obj.did
+        url_params['obj_id'] = trans_obj.obj_id
+
     return render_template(
         "datagrid/index.html", _=gettext, uniqueId=trans_id,
         is_query_tool=is_query_tool,
@@ -252,48 +281,41 @@ def panel(trans_id, is_query_tool, editor_title):
         fgcolor=fgcolor,
         # convert python boolean value to equivalent js boolean literal before
         # passing it to html template.
-        prompt_save_changes='true' if prompt_save_changes else 'false'
+        prompt_save_changes='true' if prompt_save_changes else 'false',
+        url_params=json.dumps(url_params)
     )
 
 
 @blueprint.route(
-    '/initialize/query_tool/<int:sid>/<int:did>',
+    '/initialize/query_tool/<int:sgid>/<int:sid>/<int:did>',
     methods=["POST"], endpoint='initialize_query_tool_with_did'
 )
 @blueprint.route(
-    '/initialize/query_tool/<int:sid>',
+    '/initialize/query_tool/<int:sgid>/<int:sid>',
     methods=["POST"], endpoint='initialize_query_tool'
 )
 @login_required
-def initialize_query_tool(sid, did=None):
+def initialize_query_tool(sgid, sid, did=None):
     """
     This method is responsible for instantiating and initializing
     the query tool object. It will also create a unique
     transaction id and store the information into session variable.
 
     Args:
+        sgid: Server group Id
         sid: Server Id
         did: Database Id
     """
 
     if did is None:
         # Use Maintenance database OID
-        from pgadmin.utils.driver import get_driver
-        driver = get_driver(PG_DEFAULT_DRIVER)
-        manager = driver.connection_manager(sid)
-        conn = manager.connection()
-        if conn.connected():
-            did = manager.did
-        else:
-            internal_server_error(
-                errormsg=gettext(
-                    'Server disconnected. Please connect and try again.'
-                )
-            )
-
+        manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
+        did = manager.did
     try:
-        command_obj = ObjectRegistry.get_object('query_tool', sid=sid, did=did)
+        command_obj = ObjectRegistry.get_object('query_tool', sgid=sgid,
+                                                sid=sid, did=did)
     except Exception as e:
+        app.logger.error(e)
         return internal_server_error(errormsg=str(e))
 
     # Create a unique id for the transaction
@@ -330,6 +352,8 @@ def close(trans_id):
     Args:
         trans_id: unique transaction id
     """
+    if 'gridData' not in session:
+        return make_json_response(data={'status': True})
 
     grid_data = session['gridData']
     # Return from the function if transaction id not found
@@ -346,13 +370,15 @@ def close(trans_id):
             manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(cmd_obj.sid)
             conn = manager.connection(did=cmd_obj.did, conn_id=cmd_obj.conn_id)
         except Exception as e:
+            app.logger.error(e)
             return internal_server_error(errormsg=str(e))
 
         # Release the connection
         if conn.connected():
             manager.release(did=cmd_obj.did, conn_id=cmd_obj.conn_id)
 
-        # Remove the information of unique transaction id from the session variable.
+        # Remove the information of unique transaction id from the session
+        # variable.
         grid_data.pop(str(trans_id), None)
         session['gridData'] = grid_data
 
@@ -384,6 +410,7 @@ def validate_filter(sid, did, obj_id):
         # Call validate_filter method to validate the SQL.
         status, res = sql_filter_obj.validate_filter(filter_sql)
     except Exception as e:
+        app.logger.error(e)
         return internal_server_error(errormsg=str(e))
 
     return make_json_response(data={'status': status, 'result': res})
diff --git a/web/pgadmin/tools/datagrid/static/js/datagrid.js b/web/pgadmin/tools/datagrid/static/js/datagrid.js
index c44fbb1..7c87c16 100644
--- a/web/pgadmin/tools/datagrid/static/js/datagrid.js
+++ b/web/pgadmin/tools/datagrid/static/js/datagrid.js
@@ -1,7 +1,9 @@
 define('pgadmin.datagrid', [
   'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'pgadmin.alertifyjs',
-  'sources/pgadmin', 'bundled_codemirror', 'sources/sqleditor_utils', 'wcdocker'
-], function(gettext, url_for, $, _, alertify, pgAdmin, codemirror, sqlEditorUtils) {
+  'sources/pgadmin', 'bundled_codemirror', 'sources/sqleditor_utils',
+  'backbone', 'wcdocker'
+], function(gettext, url_for, $, _, alertify, pgAdmin, codemirror,
+sqlEditorUtils, Backbone) {
     // Some scripts do export their object in the window only.
     // Generally the one, which do no have AMD support.
     var wcDocker = window.wcDocker,
@@ -12,7 +14,9 @@ define('pgadmin.datagrid', [
     if (pgAdmin.DataGrid)
       return pgAdmin.DataGrid;
 
-    pgAdmin.DataGrid = {
+    pgAdmin.DataGrid =
+    _.extend(
+    {
       init: function() {
         if (this.initialized)
             return;
@@ -112,6 +116,9 @@ define('pgadmin.datagrid', [
 
         // Load the newly created frame
         dataGridFrameType.load(pgBrowser.docker);
+        this.on("pgadmin-datagrid:transaction:created", function(trans_obj) {
+          this.launch_grid(trans_obj);
+        });
       },
 
       // This is a callback function to show data when user click on menu item.
@@ -154,6 +161,7 @@ define('pgadmin.datagrid', [
         var url_params = {
           'cmd_type': data.mnuid,
           'obj_type': d._type,
+          'sgid': parentData.server_group._id,
           'sid': parentData.server._id,
           'did': parentData.database._id,
           'obj_id': d._id
@@ -163,8 +171,7 @@ define('pgadmin.datagrid', [
         var grid_title = parentData.server.label + ' - ' + parentData.database.label + ' - '
                         + nsp_name + '.' + d.label;
 
-        // Initialize the data grid.
-        self.initialize_data_grid(baseUrl, grid_title, '', parentData.server.server_type);
+        self.create_transaction(baseUrl, null, 'false', parentData.server.server_type, '', grid_title, '');
       },
 
       // This is a callback function to show filtered data when user click on menu item.
@@ -209,10 +216,10 @@ define('pgadmin.datagrid', [
         var url_params = {
           'cmd_type': data.mnuid,
           'obj_type': d._type,
+          'sgid': parentData.server_group._id,
           'sid': parentData.server._id,
           'did': parentData.database._id,
           'obj_id': d._id
-
         };
 
         var baseUrl = url_for('datagrid.initialize_datagrid', url_params);
@@ -295,7 +302,7 @@ define('pgadmin.datagrid', [
                     success: function(res) {
                       if (res.data.status) {
                         // Initialize the data grid.
-                        self.initialize_data_grid(that.baseUrl, grid_title, sql, parentData.server.server_type);
+                        self.create_transaction(that.baseUrl, null, 'false', parentData.server.server_type, '', grid_title, sql);
                       }
                       else {
                         alertify.alert(
@@ -348,88 +355,6 @@ define('pgadmin.datagrid', [
                 parentData.server.label;
         return grid_title;
       },
-
-      initialize_data_grid: function(baseUrl, grid_title, sql_filter, server_type) {
-        var self = this;
-          self.grid_title = grid_title;
-
-        /* Ajax call to initialize the edit grid, which creates
-         * an asynchronous connection and create appropriate query
-         * for the selected node.
-         */
-        $.ajax({
-          url: baseUrl,
-          method: 'POST',
-          dataType: 'json',
-          contentType: "application/json",
-          data: JSON.stringify(sql_filter),
-          success: function(res) {
-
-            /* On successfully initialization find the dashboard panel,
-             * create new panel and add it to the dashboard panel.
-             */
-            var url_params = {
-              'trans_id': res.data.gridTransId,
-              'is_query_tool': 'false',
-              'editor_title': encodeURIComponent(self.grid_title)
-            };
-
-            var baseUrl = url_for('datagrid.panel', url_params) +
-              "?query_url=&server_type=" + encodeURIComponent(server_type);
-            var grid_title = gettext('Edit Data - ') + self.grid_title;
-            if (res.data.newBrowserTab) {
-              var newWin = window.open(baseUrl, '_blank');
-
-              // add a load listener to the window so that the title gets changed on page load
-              newWin.addEventListener("load", function() {
-                newWin.document.title = grid_title;
-              });
-            } else {
-              var propertiesPanel = pgBrowser.docker.findPanels('properties');
-              var dataGridPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, propertiesPanel[0]);
-
-              // Set panel title and icon
-              dataGridPanel.title('<span title="'+grid_title+'">'+grid_title+'</span>');
-              dataGridPanel.icon('fa fa-bolt');
-              dataGridPanel.focus();
-
-              // Listen on the panel closed event.
-              dataGridPanel.on(wcDocker.EVENT.CLOSED, function() {
-                $.ajax({
-                  url: url_for('datagrid.close', {'trans_id': res.data.gridTransId}),
-                  method: 'GET'
-                });
-              });
-
-              var openDataGridURL = function(j) {
-                // add spinner element
-                $(j).data('embeddedFrame').$container.append(self.spinner_el);
-                setTimeout(function() {
-                  var frameInitialized = $(j).data('frameInitialized');
-                  if (frameInitialized) {
-                    var frame = $(j).data('embeddedFrame');
-                    if (frame) {
-                      frame.openURL(baseUrl);
-                      frame.$container.find('.wcLoadingContainer').hide(1);
-                    }
-                  } else {
-                    openDataGridURL(j);
-                  }
-                }, 100);
-              };
-
-              openDataGridURL(dataGridPanel);
-            }
-          },
-          error: function(e) {
-            alertify.alert(
-              gettext('Error'),
-              gettext('Query Tool Initialization Error')
-            );
-          }
-        });
-      },
-
       // This is a callback function to show query tool when user click on menu item.
       show_query_tool: function(url, i, panel_title) {
         var self = this,
@@ -454,9 +379,10 @@ define('pgadmin.datagrid', [
         }
 
         var url_params = {
-          'sid': parentData.server._id
-        };
-        var url_endpoint = 'datagrid.initialize_query_tool'
+            'sgid': parentData.server_group._id,
+            'sid': parentData.server._id
+          },
+          url_endpoint = 'datagrid.initialize_query_tool';
         // If database not present then use Maintenance database
         // We will handle this at server side
         if (parentData.database) {
@@ -465,87 +391,132 @@ define('pgadmin.datagrid', [
         }
         var baseUrl = url_for(url_endpoint, url_params);
 
+        this.create_transaction(baseUrl, null, 'true', parentData.server.server_type, sURL, panel_title, '');
+      },
+      create_transaction: function(baseUrl, target, is_query_tool, server_type, sURL, panel_title, sql_filter) {
+        var self = this;
+        target =  target || self;
+
         $.ajax({
           url: baseUrl,
           method: 'POST',
           dataType: 'json',
+          data: JSON.stringify(sql_filter),
           contentType: "application/json",
           success: function(res) {
-            var grid_title = self.get_panel_title();
-            // Open the panel if frame is initialized
-            var url_params = {
-              'trans_id': res.data.gridTransId,
-              'is_query_tool': 'true',
-              'editor_title': encodeURIComponent(grid_title)
+            self.handle_connection_reset(res.data);
+            res.data.is_query_tool = is_query_tool;
+            res.data.server_type = server_type;
+            res.data.sURL = sURL;
+            res.data.panel_title = panel_title;
+            target.trigger("pgadmin-datagrid:transaction:created", res.data);
+          },
+          error: function(xhr, status, error) {
+            if (target !== self) {
+              if(xhr.status == 503 && xhr.responseJSON.info != undefined &&
+                  xhr.responseJSON.info == "CONNECTION_LOST") {
+                setTimeout(function() {
+                  target.handle_connection_lost(true);
+                });
+                return;
+              }
             }
 
-            var baseUrl = url_for('datagrid.panel', url_params) +
-                '?' + "query_url=" + encodeURI(sURL) + "&server_type=" + encodeURIComponent(parentData.server.server_type);
-
-            // Create title for CREATE/DELETE scripts
-            if (panel_title) {
-              panel_title =
-                sqlEditorUtils.capitalizeFirstLetter(panel_title) + ' script';
-            }
-            else {
-              panel_title = gettext('Query - ') + grid_title;
+            try {
+              var err = $.parseJSON(xhr.responseText);
+              alertify.alert(gettext("Query Tool Initialize Error"),
+                err.errormsg
+              );
+            } catch (e) {
+              alertify.alert(
+                e.statusText, gettext("Query Tool Initialize Error")
+              );
             }
+          }
+        });
+      },
+      launch_grid: function(trans_obj) {
+        var self = this,
+          panel_title = trans_obj.panel_title,
+          grid_title = self.get_panel_title(),
+          // Open the panel if frame is initialized
+          url_params = {
+            'trans_id': trans_obj.gridTransId,
+            'is_query_tool': trans_obj.is_query_tool,
+            'editor_title': encodeURIComponent(grid_title)
+          },
+          baseUrl = url_for('datagrid.panel', url_params) +
+            '?' + "query_url=" + encodeURI(trans_obj.sURL) + "&server_type=" + encodeURIComponent(trans_obj.server_type);
+
+        if(trans_obj.is_query_tool == 'false') {
+          panel_title = gettext('Edit Data - ') + grid_title;
+        } else {
+          // Create title for CREATE/DELETE scripts
+          if (panel_title) {
+            panel_title =
+              sqlEditorUtils.capitalizeFirstLetter(panel_title) + ' script';
+          } else {
+            panel_title = gettext('Query - ') + grid_title;
+          }
+        }
 
-            if (res.data.newBrowserTab) {
-              var newWin = window.open(baseUrl, '_blank');
-
-              // add a load listener to the window so that the title gets changed on page load
-              newWin.addEventListener("load", function() {
-                newWin.document.title = panel_title;
-              });
-            } else {
-              /* On successfully initialization find the dashboard panel,
-               * create new panel and add it to the dashboard panel.
-               */
-              var propertiesPanel = pgBrowser.docker.findPanels('properties');
-              var queryToolPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, propertiesPanel[0]);
-
-              // Set panel title and icon
-              queryToolPanel.title('<span title="'+panel_title+'">'+panel_title+'</span>');
-              queryToolPanel.icon('fa fa-bolt');
-              queryToolPanel.focus();
-
-              // Listen on the panel closed event.
-              queryToolPanel.on(wcDocker.EVENT.CLOSED, function() {
-                $.ajax({
-                  url: url_for('datagrid.close', {'trans_id': res.data.gridTransId}),
-                  method: 'GET'
-                });
-              });
+        if (trans_obj.newBrowserTab) {
+          var newWin = window.open(baseUrl, '_blank');
 
-              var openQueryToolURL = function(j) {
-                // add spinner element
-                $(j).data('embeddedFrame').$container.append(pgAdmin.DataGrid.spinner_el);
-                setTimeout(function() {
-                  var frameInitialized = $(j).data('frameInitialized');
-                  if (frameInitialized) {
-                    var frame = $(j).data('embeddedFrame');
-                    if (frame) {
-                      frame.openURL(baseUrl);
-                      frame.$container.find('.wcLoadingContainer').delay(1000).hide(1);
-                    }
-                  } else {
-                    openQueryToolURL(j);
-                  }
-                }, 100);
-              };
+          // add a load listener to the window so that the title gets changed on page load
+          newWin.addEventListener("load", function() {
+            newWin.document.title = panel_title;
+          });
+        } else {
+          /* On successfully initialization find the dashboard panel,
+           * create new panel and add it to the dashboard panel.
+           */
+          var propertiesPanel = pgBrowser.docker.findPanels('properties');
+          var queryToolPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, propertiesPanel[0]);
+
+          // Set panel title and icon
+          queryToolPanel.title('<span title="'+panel_title+'">'+panel_title+'</span>');
+          queryToolPanel.icon('fa fa-bolt');
+          queryToolPanel.focus();
+
+          // Listen on the panel closed event.
+          queryToolPanel.on(wcDocker.EVENT.CLOSED, function() {
+            $.ajax({
+              url: url_for('datagrid.close', {'trans_id': trans_obj.gridTransId}),
+              method: 'GET'
+            });
+          });
 
-              openQueryToolURL(queryToolPanel);
-            }
-          },
-          error: function(e) {
-            alertify.alert(
-              gettext("Query Tool Initialize Error")
-            );
-          }
-        });
+          var openQueryToolURL = function(j) {
+            // add spinner element
+            $(j).data('embeddedFrame').$container.append(pgAdmin.DataGrid.spinner_el);
+            setTimeout(function() {
+              var frameInitialized = $(j).data('frameInitialized');
+              if (frameInitialized) {
+                var frame = $(j).data('embeddedFrame');
+                if (frame) {
+                  frame.openURL(baseUrl);
+                  frame.$container.find('.wcLoadingContainer').delay(1000).hide(1);
+                }
+              } else {
+                openQueryToolURL(j);
+              }
+            }, 100);
+          };
+
+          openQueryToolURL(queryToolPanel);
+        }
+      },
+      handle_connection_reset: function(res) {
+        if (res.connection_reset && res.connection_reset == true) {
+          setTimeout(function() {
+            alertify.alert(gettext('Connection reset'),
+              gettext('Connection has been reset. This is because one of the reasons connection was idle for long time period and was closed, application server or database server was restarted, user session was timed out.'));
+          });
+        }
       }
-    };
+    },
+    Backbone.Events);
 
     return pgAdmin.DataGrid;
   });
diff --git a/web/pgadmin/tools/datagrid/templates/datagrid/index.html b/web/pgadmin/tools/datagrid/templates/datagrid/index.html
index ff4368d..427d51f 100644
--- a/web/pgadmin/tools/datagrid/templates/datagrid/index.html
+++ b/web/pgadmin/tools/datagrid/templates/datagrid/index.html
@@ -337,38 +337,14 @@
           loadingDiv.addClass('hide');
           }
           });
-
-    // Fetch the SQL for Scripts (eg: CREATE/UPDATE/DELETE/SELECT)
-    var script_sql = '';
-{% if script_type_url%}
-    // Call AJAX only if script type url is present
-    $.ajax({
-      url: '{{ script_type_url }}',
-      type:'GET',
-      async: false,
-      success: function(res) {
-        script_sql = res;
-      },
-      error: function(jqx) {
-        var msg = jqx.responseText;
-        /* Error from the server */
-        if (jqx.status == 410 || jqx.status == 500) {
-          try {
-            var data = $.parseJSON(jqx.responseText);
-            msg = data.errormsg;
-          } catch (e) {}
-        }
-        pgBrowser.report_error(
-          S('{{ _('Error fetching SQL for script: "%s"') }}')
-          .sprintf(msg)
-          .value(), msg
-        );
-      }
-    });
-{% endif %}
-
+    {% if script_type_url %}
+        var script_type_url = '{{ script_type_url }}';
+    {% else %}
+        var script_type_url = '';
+    {% endif %}
     // Start the query tool.
     sqlEditorController.start({{ is_query_tool }}, "{{ editor_title }}",
-                    script_sql, {{ is_new_browser_tab }}, "{{ server_type }}", {{ prompt_save_changes }});
+            script_type_url, {{ is_new_browser_tab }}, "{{ server_type }}", {{ prompt_save_changes }}, {{ url_params|safe}});
+
 });
 {% endblock %}
diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py
index 84c98d3..4545d06 100644
--- a/web/pgadmin/tools/sqleditor/__init__.py
+++ b/web/pgadmin/tools/sqleditor/__init__.py
@@ -14,7 +14,8 @@ import pickle
 import random
 import codecs
 
-from flask import Response, url_for, render_template, session, request
+from flask import Response, url_for, render_template, session, request,\
+    current_app
 from flask_babel import gettext
 from flask_security import login_required
 from pgadmin.tools.sqleditor.command import QueryToolCommand
@@ -26,6 +27,7 @@ from pgadmin.utils.driver import get_driver
 from pgadmin.utils.sqlautocomplete.autocomplete import SQLAutoComplete
 from pgadmin.misc.file_manager import Filemanager
 from pgadmin.utils.menu import MenuItem
+from pgadmin.utils.exception import ConnectionLost
 
 from config import PG_DEFAULT_DRIVER, ON_DEMAND_RECORD_COUNT
 
@@ -77,7 +79,6 @@ class SqlEditorModule(PgAdminModule):
             'when': None
         }]
 
-
     def get_panels(self):
         return []
 
@@ -363,6 +364,12 @@ def check_transaction_status(trans_id):
     Returns: status and connection object
 
     """
+
+    if 'gridData' not in session:
+        return False, gettext(
+            'Transaction ID not found in the session.'
+        ), None, None, None
+
     grid_data = session['gridData']
 
     # Return from the function if transaction id not found
@@ -381,7 +388,10 @@ def check_transaction_status(trans_id):
         conn = manager.connection(did=trans_obj.did, conn_id=trans_obj.conn_id,
                                   use_binary_placeholder=True,
                                   array_to_string=True)
+    except ConnectionLost as e:
+        raise
     except Exception as e:
+        current_app.logger.error(e)
         return False, internal_server_error(errormsg=str(e)), None, None, None
 
     if conn.connected():
@@ -408,12 +418,23 @@ def start_view_data(trans_id):
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
 
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     # get the default connection as current connection which is attached to
     # trans id holds the cursor which has query result so we cannot use that
     # connection to execute another query otherwise we'll lose query result.
 
-    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(trans_obj.sid)
-    default_conn = manager.connection(did=trans_obj.did)
+    try:
+        manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(trans_obj.sid)
+        default_conn = manager.connection(did=trans_obj.did)
+    except ConnectionLost as e:
+        raise
+    except Exception as e:
+        current_app.logger.error(e)
+        return internal_server_error(errormsg=str(e))
 
     # Connect to the Server if not connected.
     if not default_conn.connected():
@@ -435,7 +456,10 @@ def start_view_data(trans_id):
             pk_names, primary_keys = trans_obj.get_primary_keys(default_conn)
 
             # Fetch OIDs status
-            has_oids = trans_obj.has_oids(default_conn)
+            if trans_obj.object_type == 'table':
+                has_oids = trans_obj.has_oids(default_conn)
+            else:
+                has_oids = False
 
             # Fetch the applied filter.
             filter_applied = trans_obj.is_filter_applied()
@@ -466,13 +490,17 @@ def start_view_data(trans_id):
         can_filter = False
         sql = None
 
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
     return make_json_response(
         data={
             'status': status, 'result': result,
             'filter_applied': filter_applied,
             'limit': limit, 'can_edit': can_edit,
             'can_filter': can_filter, 'sql': sql,
-            'info_notifier_timeout': blueprint.info_notifier_timeout.get()
+            'info_notifier_timeout': blueprint.info_notifier_timeout.get(),
+            'connection_reset': connection_reset
         }
     )
 
@@ -495,16 +523,20 @@ def start_query_tool(trans_id):
     else:
         sql = request.args or request.form
 
+    if 'gridData' not in session:
+        return make_json_response(
+            success=0,
+            errormsg=gettext('Transaction ID not found in the session.'),
+            info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     grid_data = session['gridData']
 
     # Return from the function if transaction id not found
     if str(trans_id) not in grid_data:
         return make_json_response(
-            data={
-                'status': False, 'result': gettext('Transaction ID not found in the session.'),
-                'can_edit': False, 'can_filter': False
-            }
-        )
+            success=0,
+            errormsg=gettext('Transaction ID not found in the session.'),
+            info='DATAGRID_TRANSACTION_REQUIRED', status=404)
 
     # Fetch the object for the specified transaction id.
     # Use pickle.loads function to get the command object
@@ -529,13 +561,17 @@ def start_query_tool(trans_id):
             conn = manager.connection(did=trans_obj.did, conn_id=conn_id,
                                       use_binary_placeholder=True,
                                       array_to_string=True)
+        except ConnectionLost as e:
+            raise
         except Exception as e:
+            current_app.logger.error(e)
             return internal_server_error(errormsg=str(e))
 
         # Connect to the Server if not connected.
         if not conn.connected():
             status, msg = conn.connect()
             if not status:
+                current_app.logger.error(msg)
                 return internal_server_error(errormsg=str(msg))
 
         if conn.connected():
@@ -577,11 +613,15 @@ def start_query_tool(trans_id):
         status = False
         result = gettext('Either transaction object or session object not found.')
 
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
     return make_json_response(
         data={
             'status': status, 'result': result,
             'can_edit': can_edit, 'can_filter': can_filter,
-            'info_notifier_timeout': blueprint.info_notifier_timeout.get()
+            'info_notifier_timeout': blueprint.info_notifier_timeout.get(),
+            'connection_reset': connection_reset
         }
     )
 
@@ -602,9 +642,16 @@ def preferences(trans_id):
 
         # Check the transaction and connection status
         status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+        if error_msg == gettext(
+                'Transaction ID not found in the session.'):
+            return make_json_response(success=0, errormsg=error_msg,
+                                      info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
         if status and conn is not None \
                 and trans_obj is not None and session_obj is not None:
-            # Call the set_auto_commit and set_auto_rollback method of transaction object
+            # Call the set_auto_commit and set_auto_rollback method of
+            # transaction object
             trans_obj.set_auto_commit(blueprint.auto_commit.get())
             trans_obj.set_auto_rollback(blueprint.auto_rollback.get())
 
@@ -613,6 +660,9 @@ def preferences(trans_id):
             session_obj['command_obj'] = pickle.dumps(trans_obj, -1)
             update_session_grid_transaction(trans_id, session_obj)
 
+        connection_reset = conn.is_renewed
+        conn.is_renewed = False
+
         return make_json_response(
             data={
                 'explain_verbose': blueprint.explain_verbose.get(),
@@ -620,7 +670,8 @@ def preferences(trans_id):
                 'explain_buffers': blueprint.explain_buffers.get(),
                 'explain_timing': blueprint.explain_timing.get(),
                 'auto_commit': blueprint.auto_commit.get(),
-                'auto_rollback': blueprint.auto_rollback.get()
+                'auto_rollback': blueprint.auto_rollback.get(),
+                'connection_reset': connection_reset
             }
         )
     else:
@@ -668,6 +719,12 @@ def poll(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None and session_obj is not None:
         status, result = conn.poll(formatted_exception_msg=True, no_result=True)
         if not status:
@@ -846,6 +903,12 @@ def fetch(trans_id, fetch_all=None):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None and session_obj is not None:
         status, result = conn.async_fetchmany_2darray(fetch_row_cnt)
         if not status:
@@ -959,6 +1022,14 @@ def save(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
+    connection_reset = False
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -982,7 +1053,7 @@ def save(trans_id):
                     data={'status': status, 'result': u"{}".format(msg)}
                 )
 
-        status, res, query_res, _rowid = trans_obj.save(
+        status, res, query_res, _rowid, connection_reset = trans_obj.save(
             changed_data,
             session_obj['columns_info'],
             session_obj['client_primary_key'],
@@ -997,7 +1068,8 @@ def save(trans_id):
             'status': status,
             'result': res,
             'query_result': query_res,
-            '_rowid': _rowid
+            '_rowid': _rowid,
+            'connection_reset': connection_reset
         }
     )
 
@@ -1017,6 +1089,11 @@ def get_filter(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1025,7 +1102,11 @@ def get_filter(trans_id):
         status = False
         res = error_msg
 
-    return make_json_response(data={'status': status, 'result': res})
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
+    return make_json_response(data={'status': status, 'result': res,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route(
@@ -1047,6 +1128,12 @@ def apply_filter(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1060,7 +1147,11 @@ def apply_filter(trans_id):
         status = False
         res = error_msg
 
-    return make_json_response(data={'status': status, 'result': res})
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
+    return make_json_response(data={'status': status, 'result': res,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route(
@@ -1082,6 +1173,12 @@ def append_filter_inclusive(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1106,7 +1203,11 @@ def append_filter_inclusive(trans_id):
         status = False
         res = error_msg
 
-    return make_json_response(data={'status': status, 'result': res})
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
+    return make_json_response(data={'status': status, 'result': res,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route(
@@ -1128,6 +1229,11 @@ def append_filter_exclusive(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1171,6 +1277,12 @@ def remove_filter(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1187,7 +1299,11 @@ def remove_filter(trans_id):
         status = False
         res = error_msg
 
-    return make_json_response(data={'status': status, 'result': res})
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
+    return make_json_response(data={'status': status, 'result': res,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route(
@@ -1208,6 +1324,12 @@ def set_limit(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1224,7 +1346,11 @@ def set_limit(trans_id):
         status = False
         res = error_msg
 
-    return make_json_response(data={'status': status, 'result': res})
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
+    return make_json_response(data={'status': status, 'result': res,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route(
@@ -1240,15 +1366,20 @@ def cancel_transaction(trans_id):
         trans_id: unique transaction id
     """
 
+    if 'gridData' not in session:
+        return make_json_response(
+            success=0,
+            errormsg=gettext('Transaction ID not found in the session.'),
+            info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     grid_data = session['gridData']
 
     # Return from the function if transaction id not found
     if str(trans_id) not in grid_data:
         return make_json_response(
-            data={
-                'status': False, 'result': gettext('Transaction ID not found in the session.')
-            }
-        )
+            success=0,
+            errormsg=gettext('Transaction ID not found in the session.'),
+            info='DATAGRID_TRANSACTION_REQUIRED', status=404)
 
     # Fetch the object for the specified transaction id.
     # Use pickle.loads function to get the command object
@@ -1310,6 +1441,12 @@ def get_object_name(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1318,7 +1455,11 @@ def get_object_name(trans_id):
         status = False
         res = error_msg
 
-    return make_json_response(data={'status': status, 'result': res})
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
+    return make_json_response(data={'status': status, 'result': res,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route(
@@ -1340,6 +1481,12 @@ def set_auto_commit(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1359,7 +1506,11 @@ def set_auto_commit(trans_id):
         status = False
         res = error_msg
 
-    return make_json_response(data={'status': status, 'result': res})
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
+    return make_json_response(data={'status': status, 'result': res,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route(
@@ -1381,6 +1532,12 @@ def set_auto_rollback(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1400,7 +1557,11 @@ def set_auto_rollback(trans_id):
         status = False
         res = error_msg
 
-    return make_json_response(data={'status': status, 'result': res})
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
+    return make_json_response(data={'status': status, 'result': res,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route(
@@ -1429,6 +1590,12 @@ def auto_complete(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1441,7 +1608,11 @@ def auto_complete(trans_id):
         status = False
         res = error_msg
 
-    return make_json_response(data={'status': status, 'result': res})
+    connection_reset = conn.is_renewed
+    conn.is_renewed = False
+
+    return make_json_response(data={'status': status, 'result': res,
+                                    'connection_reset': connection_reset})
 
 
 @blueprint.route("/sqleditor.js")
diff --git a/web/pgadmin/tools/sqleditor/command.py b/web/pgadmin/tools/sqleditor/command.py
index 97f13ea..d27e5d3 100644
--- a/web/pgadmin/tools/sqleditor/command.py
+++ b/web/pgadmin/tools/sqleditor/command.py
@@ -103,7 +103,9 @@ class BaseCommand(object):
             **kwargs : N number of parameters
         """
 
-        # Save the server id and database id, namespace id, object id
+        # Save the server group id, server id and database id, namespace id,
+        # object id
+        self.sgid = kwargs['sgid'] if 'sgid' in kwargs else None
         self.sid = kwargs['sid'] if 'sid' in kwargs else None
         self.did = kwargs['did'] if 'did' in kwargs else None
 
@@ -493,7 +495,6 @@ class TableCommand(GridCommand):
                 if len(changed_data[of_type]) < 1:
                     continue
 
-
                 column_type = {}
                 column_data = {}
                 for each_col in columns_info:
@@ -639,7 +640,10 @@ class TableCommand(GridCommand):
                             except Exception:
                                 _rowid = 0
 
-                            return status, res, query_res, _rowid
+                            connection_reset = conn.is_renewed
+                            conn.is_renewed = False
+
+                            return status, res, query_res, _rowid, connection_reset
 
                         # Select added row from the table
                         if 'select_sql' in item:
@@ -660,7 +664,9 @@ class TableCommand(GridCommand):
                                 except Exception:
                                     _rowid = 0
 
-                                return status, sel_res, query_res, _rowid
+                                connection_reset = conn.is_renewed
+                                conn.is_renewed = False
+                                return status, sel_res, query_res, _rowid, connection_reset
 
                             if 'rows' in sel_res and len(sel_res['rows']) > 0:
                                 row_added = {item['client_row']: sel_res['rows'][0]}
@@ -676,8 +682,9 @@ class TableCommand(GridCommand):
 
             # Commit the transaction if there is no error found
             conn.execute_void('COMMIT;')
-
-        return status, res, query_res, _rowid
+        connection_reset = conn.is_renewed
+        conn.is_renewed = False
+        return status, res, query_res, _rowid, connection_reset
 
 
 class ViewCommand(GridCommand):
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index dbc416e..fcd8703 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -17,18 +17,19 @@ define('tools.querytool', [
     'react', 'react-dom',
     'sources/sqleditor/keyboard_shortcuts',
     'sources/sqleditor/query_tool_actions',
-  'sources/../bundle/slickgrid',
+    'pgadmin.datagrid',
+    'sources/../bundle/slickgrid',
     'pgadmin.file_manager',
     'backgrid.sizeable.columns',
     'slick.pgadmin.formatters',
     'slick.pgadmin.editors',
-    'pgadmin.browser'
+    'pgadmin.browser',
+    'pgadmin.tools.user_management'
 ], function(
   babelPollyfill,gettext, url_for, $, _, S, alertify, pgAdmin, Backbone, codemirror,
   pgExplain, GridSelector, ActiveCellCapture, clipboard, copyData, RangeSelectionHelper, handleQueryOutputKeyboardEvent,
   XCellSelectionModel, setStagedRows,  SqlEditorUtils, HistoryBundle, queryHistory, React, ReactDOM,
-  keyboardShortcuts
-, queryToolActions) {
+  keyboardShortcuts, queryToolActions, Datagrid) {
     /* Return back, this has been called more than once */
     if (pgAdmin.SqlEditor)
       return pgAdmin.SqlEditor;
@@ -41,6 +42,12 @@ define('tools.querytool', [
 
   var is_query_running = false;
 
+  var is_new_transaction_required = function(xhr) {
+    return xhr.status == 404 && xhr.responseJSON &&
+                xhr.responseJSON.info &&
+                xhr.responseJSON.info == 'DATAGRID_TRANSACTION_REQUIRED'
+  }
+
   // Defining Backbone view for the sql grid.
   var SQLEditorView = Backbone.View.extend({
     initialize: function (opts) {
@@ -347,6 +354,7 @@ define('tools.querytool', [
               contentType: "application/json",
               data: JSON.stringify(self.data),
               success: function (res) {
+                handle_connection_reset(res.data);
                 var result = [];
 
                 _.each(res.data.result, function (obj, key) {
@@ -398,6 +406,14 @@ define('tools.querytool', [
                   from: {line: self.current_line, ch: start},
                   to: {line: self.current_line, ch: end}
                 });
+              },
+              error:function(e) {
+                if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                  return pgAdmin.Browser.UserManagement.pga_login();
+                }
+                if(is_new_transaction_required(e)) {
+                  return self.init_transaction();
+                }
               }
             });
           }.bind(ctx)
@@ -1010,7 +1026,10 @@ define('tools.querytool', [
             self.update_msg_history(false,
               gettext('Not connected to the server or the connection to the server has been closed.')
             );
-            return;
+          }
+
+          if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+            pgAdmin.Browser.UserManagement.pga_login();
           }
         }
       });
@@ -1580,14 +1599,129 @@ define('tools.querytool', [
     Backbone.Events,
     {
       initialize: function (container, opts) {
+        self= this;
         this.container = container;
+        if (!alertify.dlgGetServerPass) {
+          alertify.dialog('dlgGetServerPass', function factory() {
+            return {
+              main: function(
+                title, message
+              ) {
+                this.set('title', title);
+                this.setting('message',message);
+              },
+              setup:function() {
+                return {
+                  buttons:[
+                    {
+                      text: gettext("OK"), key: 13, className: "btn btn-primary"
+                    },
+                    {
+                      text: gettext("Cancel"), className: "btn btn-danger"
+                    }
+                  ],
+                  focus: { element: '#password', select: true },
+                  options: {
+                    modal: 0, resizable: false, maximizable: false, pinnable: false
+                  }
+                };
+              },
+              build:function() {},
+              settings:{
+                message: null
+              },
+              prepare:function() {
+                this.setContent(this.setting('message'));
+              },
+              callback: function(closeEvent) {
+                if (closeEvent.button.text == gettext("OK")) {
+                  var passdata = $(this.elements.content).find('#frmPassword').serialize();
+                   self.init_connection(false, passdata);
+                }
+              }
+            };
+          });
+        }
+        this.on("pgadmin-datagrid:transaction:created", function(trans_obj) {
+          self.transId = trans_obj.gridTransId;
+          if (self.is_query_tool) {
+            alertify.success(gettext('New SQL editor session created.'));
+          } else {
+            alertify.success(gettext('New Data grid session created.'));
+          }
+        });
+        pgBrowser.Events.on('pgadmin:user:logged-in', function() {
+          self.init_transaction();
+        });
+      },
+
+      init_transaction: function() {
+        var url_endpoint;
+        if (this.is_query_tool) {
+          url_endpoint = 'datagrid.initialize_query_tool';
+
+          // If database not present then use Maintenance database
+          // We will handle this at server side
+          if (this.url_params.did) {
+            url_endpoint = 'datagrid.initialize_query_tool_with_did';
+          }
+
+        } else {
+          url_endpoint = 'datagrid.initialize_datagrid';
+        }
+
+        var baseUrl = url_for(url_endpoint, this.url_params);
+
+        Datagrid.create_transaction(baseUrl, this, this.is_query_tool,
+            this.server_type, '', '', '');
       },
 
+      handle_connection_lost: function(create_transaction) {
+        var self= this;
+        alertify.confirm(
+            gettext('Connection lost'),
+            gettext('Would you like to reconnect to the server?'),
+            function() {
+              self.init_connection(create_transaction);
+            }, function() {});
+      },
+
+      init_connection: function(create_transaction, passdata) {
+        var self = this;
+        $.post(url_for('NODE-server.connect_id', {'gid': this.url_params.sgid,
+                                                  'sid': this.url_params.sid}),
+                                                  passdata)
+        .done(function(res) {
+          if (res.success == 1) {
+            Datagrid.handle_connection_reset({'connection_reset': true});
+            alertify.success(res.info);
+            if (create_transaction) {
+              self.init_transaction();
+            }
+          }
+        })
+        .fail(function(xhr, status, error) {
+          if (pgAdmin.Browser.UserManagement.is_pga_login_required(xhr)) {
+            pgAdmin.Browser.UserManagement.pga_login();
+          } else {
+            if(xhr.responseJSON &&
+                xhr.responseJSON.result) {
+              alertify.dlgGetServerPass(gettext('Connect to Server'),
+                xhr.responseJSON.result);
+            } else {
+              alertify.dlgGetServerPass(gettext('Connect to Server'),
+                xhr.responseText);
+            }
+          }
+        });
+      },
       /* This function is used to create instance of SQLEditorView,
        * call the render method of the grid view to render the backgrid
        * header and loading icon and start execution of the sql query.
        */
-      start: function (is_query_tool, editor_title, script_sql, is_new_browser_tab, server_type, prompt_save_changes) {
+      start: function (is_query_tool, editor_title, script_type_url,
+          is_new_browser_tab, server_type, prompt_save_changes, url_params
+      ) {
         var self = this;
 
         self.is_query_tool = is_query_tool;
@@ -1603,6 +1737,8 @@ define('tools.querytool', [
         self.close_on_save = false;
         self.server_type = server_type;
         self.prompt_save_changes = prompt_save_changes;
+        self.url_params = url_params;
+        self.script_type_url = script_type_url;
 
         // We do not allow to call the start multiple times.
         if (self.gridView)
@@ -1620,6 +1756,59 @@ define('tools.querytool', [
         // Render the header
         self.gridView.render();
 
+        if (self.is_query_tool) {
+          // Fetch the SQL for Scripts (eg: CREATE/UPDATE/DELETE/SELECT)
+          // Call AJAX only if script type url is present
+          if (script_type_url) {
+            $.ajax({
+              url: script_type_url,
+              type:'GET',
+              success: function(res) {
+                self.gridView.query_tool_obj.refresh();
+                if (res && res !== '') {
+                  self.gridView.query_tool_obj.setValue(res);
+                }
+                self.init_events();
+              },
+              error: function(jqx) {
+                var msg = jqx.responseText;
+                self.init_events();
+
+                if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                  return pgAdmin.Browser.UserManagement.pga_login();
+                }
+
+                /* Error from the server */
+                if (jqx.status == 410 || jqx.status == 500) {
+                  try {
+                    var data = $.parseJSON(jqx.responseText);
+                    msg = data.errormsg;
+                  } catch (e) {}
+                }
+                pgBrowser.report_error(
+                  S(gettext("Error fetching SQL for script: %s.")).sprintf(msg).value()
+                );
+              }
+            });
+          } else {
+            self.init_events();
+          }
+        }
+        else {
+          // Disable codemirror by setting cursor to nocursor and background to dark.
+          self.init_events();
+          self.gridView.query_tool_obj.setOption("readOnly", 'nocursor');
+          var cm = self.gridView.query_tool_obj.getWrapperElement();
+          if (cm) {
+            cm.className += ' bg-gray-1 opacity-5';
+          }
+          self.disable_tool_buttons(true);
+          self.execute_data_query();
+        }
+      },
+
+      init_events: function() {
+        var self = this;
         // Listen to the file manager button events
         pgAdmin.Browser.Events.on('pgadmin-storage:finish_btn:select_file', self._select_file_handler, self);
         pgAdmin.Browser.Events.on('pgadmin-storage:finish_btn:create_file', self._save_file_handler, self);
@@ -1653,23 +1842,6 @@ define('tools.querytool', [
         // Indentation related
         self.on('pgadmin-sqleditor:indent_selected_code', self._indent_selected_code, self);
         self.on('pgadmin-sqleditor:unindent_selected_code', self._unindent_selected_code, self);
-
-        if (self.is_query_tool) {
-          self.gridView.query_tool_obj.refresh();
-          if (script_sql && script_sql !== '') {
-            self.gridView.query_tool_obj.setValue(script_sql);
-          }
-        }
-        else {
-          // Disable codemirror by setting cursor to nocursor and background to dark.
-          self.gridView.query_tool_obj.setOption("readOnly", 'nocursor');
-          var cm = self.gridView.query_tool_obj.getWrapperElement();
-          if (cm) {
-            cm.className += ' bg-gray-1 opacity-5';
-          }
-          self.disable_tool_buttons(true);
-          self.execute_data_query();
-        }
       },
 
       // This function checks if there is any dirty data in the grid before
@@ -1729,7 +1901,7 @@ define('tools.querytool', [
           method: 'GET',
           success: function (res) {
             if (res.data.status) {
-
+              Datagrid.handle_connection_reset(res.data);
               self.can_edit = res.data.can_edit;
               self.can_filter = res.data.can_filter;
               self.info_notifier_timeout = res.data.info_notifier_timeout;
@@ -1778,11 +1950,27 @@ define('tools.querytool', [
               );
               return;
             }
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              self.init_transaction();
+            }
 
             var msg = e.responseText;
-            if (e.responseJSON != undefined &&
-              e.responseJSON.errormsg != undefined)
-              msg = e.responseJSON.errormsg;
+            if (e.responseJSON != undefined) {
+              if(e.responseJSON.errormsg != undefined) {
+                msg = e.responseJSON.errormsg;
+              }
+
+              if(e.status == 503 && e.responseJSON.info != undefined &&
+                  e.responseJSON.info == "CONNECTION_LOST") {
+                setTimeout(function() {
+                  self.handle_connection_lost();
+                });
+              }
+            }
 
             self.update_msg_history(false, msg);
           }
@@ -1886,6 +2074,10 @@ define('tools.querytool', [
                   return;
                 }
 
+                if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                  return pgAdmin.Browser.UserManagement.pga_login();
+                }
+
                 var msg = e.responseText;
                 if (e.responseJSON != undefined &&
                   e.responseJSON.errormsg != undefined)
@@ -2392,6 +2584,7 @@ define('tools.querytool', [
                 data = [];
 
               if (res.data.status) {
+                Datagrid.handle_connection_reset(res.data);
                 if(is_added) {
                   // Update the rows in a grid after addition
                   dataView.beginUpdate();
@@ -2512,6 +2705,10 @@ define('tools.querytool', [
                   return;
                 }
 
+                if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                  pgAdmin.Browser.UserManagement.pga_login();
+                }
+
               var msg = e.responseText;
               if (e.responseJSON != undefined &&
                 e.responseJSON.errormsg != undefined)
@@ -2653,9 +2850,13 @@ define('tools.querytool', [
               self.is_query_changed = false;
             },
             error: function(e) {
+              self.trigger('pgadmin-sqleditor:loading-icon:hide');
+              if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                return pgAdmin.Browser.UserManagement.pga_login();
+              }
+
               var errmsg = $.parseJSON(e.responseText).errormsg;
               alertify.error(errmsg);
-              self.trigger('pgadmin-sqleditor:loading-icon:hide');
               // hide cursor
               $busy_icon_div.removeClass('show_progress');
             }
@@ -2699,6 +2900,9 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
 
               var errmsg = $.parseJSON(e.responseText).errormsg;
               setTimeout(
@@ -2787,6 +2991,7 @@ define('tools.querytool', [
             if (res.data.status) {
               $('#filter').removeClass('hidden');
               $('#editor-panel').addClass('sql-editor-busy-fetching');
+              Datagrid.handle_connection_reset(res.data);
               self.gridView.filter_obj.refresh();
 
               if (res.data.result == null)
@@ -2806,6 +3011,14 @@ define('tools.querytool', [
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             var msg;
             if (e.readyState == 0) {
               msg =
@@ -2860,6 +3073,7 @@ define('tools.querytool', [
           data: JSON.stringify(data),
           success: function (res) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            Datagrid.handle_connection_reset(res.data);
             setTimeout(
               function () {
                 if (res.data.status) {
@@ -2874,6 +3088,14 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             setTimeout(
               function () {
                 if (e.readyState == 0) {
@@ -2930,6 +3152,7 @@ define('tools.querytool', [
           data: JSON.stringify(data),
           success: function (res) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            Datagrid.handle_connection_reset(res.data);
             setTimeout(
               function () {
                 if (res.data.status) {
@@ -2944,6 +3167,13 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
 
             setTimeout(
               function () {
@@ -2981,6 +3211,7 @@ define('tools.querytool', [
           method: 'POST',
           success: function (res) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            Datagrid.handle_connection_reset(res.data);
             setTimeout(
               function () {
                 if (res.data.status) {
@@ -2995,6 +3226,14 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             setTimeout(
               function () {
                 if (e.readyState == 0) {
@@ -3034,6 +3273,7 @@ define('tools.querytool', [
           data: JSON.stringify(sql),
           success: function (res) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            Datagrid.handle_connection_reset(res.data);
             setTimeout(
               function () {
                 if (res.data.status) {
@@ -3050,6 +3290,14 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             setTimeout(
               function () {
                 if (e.readyState == 0) {
@@ -3171,6 +3419,7 @@ define('tools.querytool', [
           data: JSON.stringify(limit),
           success: function (res) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            Datagrid.handle_connection_reset(res.data);
             setTimeout(
               function () {
                 if (res.data.status) {
@@ -3184,6 +3433,14 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             setTimeout(
               function () {
                 if (e.readyState == 0) {
@@ -3293,6 +3550,7 @@ define('tools.querytool', [
               // Highlight the error in the sql panel
               self._highlight_error(res.data.result);
             }
+            Datagrid.handle_connection_reset(res.data);
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
@@ -3306,11 +3564,26 @@ define('tools.querytool', [
               return;
             }
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              self.init_transaction();
+            }
             var msg = e.responseText;
-            if (e.responseJSON != undefined &&
-              e.responseJSON.errormsg != undefined)
-              msg = e.responseJSON.errormsg;
+            if (e.responseJSON != undefined) {
+              if(e.responseJSON.errormsg != undefined) {
+                msg = e.responseJSON.errormsg;
+              }
 
+              if(e.status == 503 && e.responseJSON.info != undefined &&
+                  e.responseJSON.info == "CONNECTION_LOST") {
+                setTimeout(function() {
+                  self.handle_connection_lost();
+                });
+              }
+            }
             self.update_msg_history(false, msg);
           }
         });
@@ -3404,6 +3677,10 @@ define('tools.querytool', [
               return;
             }
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
             var msg = e.responseText;
             if (e.responseJSON != undefined &&
               e.responseJSON.errormsg != undefined)
@@ -3442,6 +3719,7 @@ define('tools.querytool', [
           contentType: "application/json",
           data: JSON.stringify(auto_rollback),
           success: function (res) {
+            Datagrid.handle_connection_reset(res.data);
             if (!res.data.status)
               alertify.alert(gettext('Auto Rollback Error'), res.data.result);
           },
@@ -3453,6 +3731,10 @@ define('tools.querytool', [
               return;
             }
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
             var msg = e.responseText;
             if (e.responseJSON != undefined &&
               e.responseJSON.errormsg != undefined)
@@ -3474,13 +3756,14 @@ define('tools.querytool', [
           auto_commit = false;
         }
 
-        // Make ajax call to change the limit
+        // Make ajax call to toggle auto commit
         $.ajax({
           url: url_for('sqleditor.auto_commit', {'trans_id': self.transId}),
           method: 'POST',
           contentType: "application/json",
           data: JSON.stringify(auto_commit),
           success: function (res) {
+            Datagrid.handle_connection_reset(res.data);
             if (!res.data.status)
               alertify.alert(gettext('Auto Commit Error'), res.data.result);
           },
@@ -3492,6 +3775,14 @@ define('tools.querytool', [
               return;
             }
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             var msg = e.responseText;
             if (e.responseJSON != undefined &&
               e.responseJSON.errormsg != undefined)
@@ -3525,6 +3816,7 @@ define('tools.querytool', [
           contentType: "application/json",
           data: JSON.stringify(data),
           success: function (res) {
+            Datagrid.handle_connection_reset(res.data);
             if (res.success == undefined || !res.success) {
               alertify.alert(gettext('Explain options error'),
                 gettext("Error occurred while setting verbose option in explain.")
@@ -3532,6 +3824,15 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             alertify.alert(gettext('Explain options error'),
               gettext("Error occurred while setting verbose option in explain.")
             );
@@ -3563,6 +3864,7 @@ define('tools.querytool', [
           contentType: "application/json",
           data: JSON.stringify(data),
           success: function (res) {
+            Datagrid.handle_connection_reset(res.data);
             if (res.success == undefined || !res.success) {
               alertify.alert(gettext('Explain options error'),
                 gettext("Error occurred while setting costs option in explain.")
@@ -3570,6 +3872,14 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             alertify.alert(gettext('Explain options error'),
               gettext("Error occurred while setting costs option in explain.")
             );
@@ -3600,6 +3910,7 @@ define('tools.querytool', [
           contentType: "application/json",
           data: JSON.stringify(data),
           success: function (res) {
+            Datagrid.handle_connection_reset(res.data);
             if (res.success == undefined || !res.success) {
               alertify.alert(gettext('Explain options error'),
                 gettext("Error occurred while setting buffers option in explain.")
@@ -3607,6 +3918,14 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             alertify.alert(gettext('Explain options error'),
               gettext("Error occurred while setting buffers option in explain.")
             );
@@ -3636,6 +3955,7 @@ define('tools.querytool', [
           contentType: "application/json",
           data: JSON.stringify(data),
           success: function (res) {
+            Datagrid.handle_connection_reset(res.data);
             if (res.success == undefined || !res.success) {
               alertify.alert(gettext('Explain options error'),
                 gettext("Error occurred while setting timing option in explain.")
@@ -3643,6 +3963,14 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             alertify.alert(gettext('Explain options error'),
               gettext("Error occurred while setting timing option in explain.")
             );
@@ -3729,6 +4057,7 @@ define('tools.querytool', [
           method: 'GET',
           success: function (res) {
             if (res.data) {
+              Datagrid.handle_connection_reset(res.data);
               explain_verbose = res.data.explain_verbose;
               explain_costs = res.data.explain_costs;
               explain_buffers = res.data.explain_buffers;
@@ -3739,6 +4068,9 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
             updateUI();
             alertify.alert(gettext('Get Preferences error'),
               gettext("Error occurred while getting query tool options.")
@@ -3748,6 +4080,8 @@ define('tools.querytool', [
       },
       close: function () {
         var self = this;
+
+        pgBrowser.Events.off('pgadmin:user:logged-in', this.init_transaction);
         _.each(window.top.pgAdmin.Browser.docker.findPanels('frm_datagrid'), function (panel) {
           if (panel.isVisible()) {
             window.onbeforeunload = null;
diff --git a/web/pgadmin/tools/user_management/__init__.py b/web/pgadmin/tools/user_management/__init__.py
index 3eb96f5..c0d6f10 100644
--- a/web/pgadmin/tools/user_management/__init__.py
+++ b/web/pgadmin/tools/user_management/__init__.py
@@ -13,7 +13,7 @@ import simplejson as json
 import re
 
 from flask import render_template, request, \
-    url_for, Response, abort
+    url_for, Response, abort, current_app
 from flask_babel import gettext as _
 from flask_security import login_required, roles_required, current_user
 from flask_security.utils import encrypt_password
@@ -73,7 +73,7 @@ class UserManagementModule(PgAdminModule):
             'user_management.roles', 'user_management.role',
             'user_management.update_user', 'user_management.delete_user',
             'user_management.create_user', 'user_management.users',
-            'user_management.user'
+            'user_management.user', current_app.login_manager.login_view
         ]
 
 
diff --git a/web/pgadmin/tools/user_management/static/js/user_management.js b/web/pgadmin/tools/user_management/static/js/user_management.js
index d51d6b4..a55594b 100644
--- a/web/pgadmin/tools/user_management/static/js/user_management.js
+++ b/web/pgadmin/tools/user_management/static/js/user_management.js
@@ -122,6 +122,95 @@ define([
         alertify.ChangePassword(title, url).resizeTo('75%','70%');
       },
 
+      is_pga_login_required(xhr) {
+        return xhr.status == 401 && xhr.responseJSON &&
+                xhr.responseJSON.info &&
+                xhr.responseJSON.info == 'PGADMIN_LOGIN_REQUIRED'
+      },
+
+      // Callback to draw pgAdmin4 login dialog.
+      pga_login: function(url) {
+        var title = gettext('pgAdmin 4 login');
+        url = url || url_for('security.login');
+        if(!alertify.PgaLogin) {
+          alertify.dialog('PgaLogin' ,function factory() {
+            return {
+              main: function(title, url) {
+                this.set({
+                  'title': title,
+                  'url': url
+                });
+              },
+              build: function() {
+                alertify.pgDialogBuild.apply(this)
+              },
+              settings:{
+                  url: undefined
+              },
+              setup:function() {
+                return {
+                  buttons: [{
+                    text: gettext('Close'), key: 27,
+                    className: 'btn btn-danger fa fa-lg fa-times pg-alertify-button',
+                    attrs:{name:'close', type:'button'}
+                  }],
+                  // Set options for dialog
+                  options: {
+                    //disable both padding and overflow control.
+                    padding : !1,
+                    overflow: !1,
+                    modal: true,
+                    resizable: true,
+                    maximizable: true,
+                    pinnable: false,
+                    closableByDimmer: false,
+                    closable: false
+                  }
+                };
+              },
+              hooks: {
+                // Triggered when the dialog is closed
+                onclose: function() {
+                  // Clear the view
+                  return setTimeout((function() {
+                    return alertify.PgaLogin().destroy();
+                  }));
+                }
+              },
+              prepare: function() {
+                // create the iframe element
+                var self = this,
+                    iframe = document.createElement('iframe'),
+                    url = this.setting('url');
+
+                iframe.onload = function() {
+                  var doc = this.contentDocument || this.contentWindow.document;
+                  if (doc.location.href.indexOf(url) == -1) {
+                    // login successful.
+
+                    this.contentWindow.stop();
+                    this.onload = null;
+
+                    // close the dialog.
+                    self.close();
+                    pgBrowser.Events.trigger('pgadmin:user:logged-in');
+                  }
+                };
+
+                iframe.frameBorder = "no";
+                iframe.width = "100%";
+                iframe.height = "100%";
+                iframe.src = url;
+                // add it to the dialog
+                self.elements.content.appendChild(iframe);
+              }
+            };
+          });
+        }
+
+        alertify.PgaLogin(title, url).resizeTo('75%','70%');
+      },
+
       // Callback to draw User Management Dialog.
       show_users: function(action, item, params) {
         if (!userInfo['is_admin']) return;
diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py
index 7c9fb07..ad31abe 100644
--- a/web/pgadmin/utils/driver/psycopg2/__init__.py
+++ b/web/pgadmin/utils/driver/psycopg2/__init__.py
@@ -162,6 +162,7 @@ class Connection(BaseConnection):
         self.reconnecting = False
         self.use_binary_placeholder = use_binary_placeholder
         self.array_to_string = array_to_string
+        self.is_renewed = False
 
         super(Connection, self).__init__()
 
@@ -202,6 +203,7 @@ class Connection(BaseConnection):
 
     def connect(self, **kwargs):
         if self.conn:
+            self.is_renewed = True
             if self.conn.closed:
                 self.conn = None
             else:
@@ -1117,10 +1119,12 @@ Failed to execute query (execute_void) for the server #{server_id} - {conn_id}
             if not self.conn.closed:
                 return True
             self.conn = None
+            self.is_renewed = True
         return False
 
     def reset(self):
         if self.conn:
+            self.is_renewed = True
             if self.conn.closed:
                 self.conn = None
         pg_conn = None
@@ -1184,6 +1188,7 @@ Failed to reset the connection to the server due to following error:
     def _release(self):
         if self.wasConnected:
             if self.conn:
+                self.is_renewed = True
                 self.conn.close()
                 self.conn = None
             self.password = None
@@ -1786,6 +1791,7 @@ WHERE db.oid = {0}""".format(did))
                 use_binary_placeholder=conn_info['use_binary_placeholder'],
                 array_to_string=conn_info['array_to_string']
             )
+
             # only try to reconnect if connection was connected previously.
             if conn_info['wasConnected']:
                 try:
@@ -1795,6 +1801,7 @@ WHERE db.oid = {0}""".format(did))
                     )
                     # This will also update wasConnected flag in connection so
                     # no need to update the flag manually.
+                    conn.is_renewed = True
                 except Exception as e:
                     current_app.logger.exception(e)
                     self.connections.pop(conn_info['conn_id'])
diff --git a/web/pgadmin/utils/exception.py b/web/pgadmin/utils/exception.py
index d50c026..f010d35 100644
--- a/web/pgadmin/utils/exception.py
+++ b/web/pgadmin/utils/exception.py
@@ -28,7 +28,7 @@ class ConnectionLost(HTTPException):
 
     @property
     def name(self):
-        return HTTP_STATUS_CODES.get(505, 'Service Unavailable')
+        return HTTP_STATUS_CODES.get(503, 'Service Unavailable')
 
     def get_response(self, environ=None):
         return service_unavailable(
diff --git a/web/pgadmin/utils/session.py b/web/pgadmin/utils/session.py
index 437539c..b7d4595 100644
--- a/web/pgadmin/utils/session.py
+++ b/web/pgadmin/utils/session.py
@@ -24,6 +24,9 @@ import random
 import string
 import time
 from uuid import uuid4
+from flask import current_app, request, flash, redirect
+from flask_login import login_url
+from pgadmin.utils.ajax import make_json_response
 
 try:
     from cPickle import dump, load
@@ -298,3 +301,32 @@ def create_session_interface(app, skip_paths=[]):
             1000
         ), skip_paths,
         datetime.timedelta(days=1))
+
+
+def pga_unauthorised():
+
+    lm = current_app.login_manager
+    login_message = None
+
+    if lm.login_message:
+        if lm.localize_callback is not None:
+            login_message = lm.localize_callback(lm.login_message)
+        else:
+            login_message = lm.login_message
+
+    if not lm.login_view or request.is_xhr:
+        # Only 401 is not enough to distinguish pgAdmin login is required.
+        # There are other cases when we return 401. For eg. wrong password
+        # supplied while connecting to server.
+        # So send additional 'info' message.
+        return make_json_response(
+            status=401,
+            success=0,
+            errormsg=login_message,
+            info='PGADMIN_LOGIN_REQUIRED'
+        )
+
+    if login_message:
+        flash(login_message, category=lm.login_message_category)
+
+    return redirect(login_url(lm.login_view, request.url))

Reply via email to