public inbox for [email protected]help / color / mirror / Atom feed
RM#1387 [Add-on PATCH] Bad handling of missing connection database server 7+ messages / 4 participants [nested] [flat]
* RM#1387 [Add-on PATCH] Bad handling of missing connection database server @ 2016-08-30 13:46 Ashesh Vashi <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Ashesh Vashi @ 2016-08-30 13:46 UTC (permalink / raw) To: Dave Page <[email protected]>; +Cc: pgadmin-hackers Hi Dave, Please find the add-on patch on top of the current change. Can you please take a look at it? This mainly works on the postgres driver to make an attempt to reconnect the server. -- Thanks & Regards, Ashesh Vashi EnterpriseDB INDIA: Enterprise PostgreSQL Company <http://www.enterprisedb.com; *http://www.linkedin.com/in/asheshvashi* <http://www.linkedin.com/in/asheshvashi; -- Sent via pgadmin-hackers mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgadmin-hackers Attachments: [application/octet-stream] RM1387_addon.patch (16.1K, 3-RM1387_addon.patch) download | inline diff: diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py index 4271199..0b6c6ca 100644 --- a/web/pgadmin/browser/server_groups/servers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/__init__.py @@ -818,7 +818,7 @@ class ServerNode(PGChildNodeView): 'servers/password.html', server_label=server.name, username=server.username, - errmsg=e.message if e.message else str(e), + errmsg=getattr(e, 'message', str(e)), _=gettext ) ) diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py index e3a9e96..e93a82b 100644 --- a/web/pgadmin/utils/driver/psycopg2/__init__.py +++ b/web/pgadmin/utils/driver/psycopg2/__init__.py @@ -131,6 +131,9 @@ class Connection(BaseConnection): * _release() - Release the connection object of psycopg2 + * _reconnect() + - Attempt to reconnect to the database + * _wait(conn) - This method is used to wait for asynchronous connection. This is a blocking call. @@ -181,6 +184,8 @@ class Connection(BaseConnection): self.row_count = 0 self.__notices = None self.password = None + self.wasConnected = False + self.reconnecting = False super(Connection, self).__init__() @@ -233,7 +238,8 @@ class Connection(BaseConnection): encpass = self.password or getattr(mgr, 'password', None) # Reset the existing connection password - self.password = None + if self.reconnecting is not False: + self.password = None if encpass: # Fetch Logged in User Details. @@ -301,8 +307,44 @@ Failed to connect to the database server(#{server_id}) for connection ({conn_id} return False, msg self.conn = pg_conn - self.__backend_pid = pg_conn.get_backend_pid() + self.wasConnected = True + try: + status, msg = self._initialize(conn_id, **kwargs) + except Exception as e: + current_app.logger.exception(e) + self.conn = None + if not self.reconnecting: + self.wasConnected = False + raise e + + if status: + mgr._update_password(encpass) + else: + if not self.reconnecting: + self.wasConnected = False + + return status, msg + + def _initialize(self, conn_id, **kwargs): self.execution_aborted = False + self.__backend_pid = self.conn.get_backend_pid() + + setattr(g, "{0}#{1}".format( + self.manager.sid, + self.conn_id.encode('utf-8') + ), None) + + status, cur = self.__cursor() + formatted_exception_msg = self._formatted_exception_msg + mgr = self.manager + + def _execute(cur, query, params=None): + try: + self.__internal_blocking_execute(cur, query, params) + except psycopg2.Error as pe: + cur.close() + return formatted_exception_msg(pe, False) + return None # autocommit flag does not work with asynchronous connections. # By default asynchronous connection runs in autocommit mode. @@ -313,22 +355,22 @@ Failed to connect to the database server(#{server_id}) for connection ({conn_id} self.conn.autocommit = True register_date_typecasters(self.conn) - status, res = self.execute_scalar(""" + status = _execute(cur, """ SET DateStyle=ISO; SET client_min_messages=notice; SET bytea_output=escape; SET client_encoding='UNICODE';""") - if not status: + if status is not None: self.conn.close() self.conn = None - return False, res + return False, status if mgr.role: - status, res = self.execute_scalar(u"SET ROLE TO %s", [mgr.role]) + status = _execute(cur, u"SET ROLE TO %s", [mgr.role]) - if not status: + if status is not None: self.conn.close() self.conn = None current_app.logger.error(""" @@ -337,35 +379,38 @@ Connect to the database server (#{server_id}) for connection ({conn_id}), but - """.format( server_id=self.manager.sid, conn_id=conn_id, - msg=res + msg=status ) ) return False, \ _("Failed to setup the role with error message:\n{0}").format( - res + status ) if mgr.ver is None: - status, res = self.execute_scalar("SELECT version()") + status = _execute(cur, "SELECT version()") - if status: - mgr.ver = res - mgr.sversion = pg_conn.server_version - else: + if status is not None: self.conn.close() self.conn = None + self.wasConneted = False current_app.logger.error(""" Failed to fetch the version information on the established connection to the database server (#{server_id}) for '{conn_id}' with below error message: {msg} """.format( server_id=self.manager.sid, conn_id=conn_id, - msg=res + msg=status ) ) - return False, res + return False, status + + if cur.rowcount > 0: + row = cur.fetchmany(1)[0] + mgr.ver = row['version'] + mgr.sversion = self.conn.server_version - status, res = self.execute_dict(""" + status = _execute(cur, """ SELECT db.oid as did, db.datname, db.datallowconn, pg_encoding_to_char(db.encoding) AS serverencoding, has_database_privilege(db.oid, 'CREATE') as cancreate, datlastsysoid @@ -373,16 +418,17 @@ FROM pg_database db WHERE db.datname = current_database()""") - if status: + if status is None: mgr.db_info = mgr.db_info or dict() - f_row = res['rows'][0] - mgr.db_info[f_row['did']] = f_row.copy() + if cur.rowcount > 0: + res = cur.fetchmany(1)[0] + mgr.db_info[res['did']] = res.copy() - # We do not have database oid for the maintenance database. - if len(mgr.db_info) == 1: - mgr.did = f_row['did'] + # We do not have database oid for the maintenance database. + if len(mgr.db_info) == 1: + mgr.did = res['did'] - status, res = self.execute_dict(""" + status = _execute(cur, """ SELECT oid as id, rolname as name, rolsuper as is_superuser, rolcreaterole as can_create_role, rolcreatedb as can_create_db @@ -391,28 +437,34 @@ FROM WHERE rolname = current_user""") - if status: + if status is None: mgr.user_info = dict() - f_row = res['rows'][0] - mgr.user_info = f_row.copy() + if cur.rowcount > 0: + mgr.user_info = cur.fetchmany(1)[0] if 'password' in kwargs: mgr.password = kwargs['password'] + server_types = None if 'server_types' in kwargs and isinstance(kwargs['server_types'], list): - for st in kwargs['server_types']: - if st.instanceOf(mgr.ver): - mgr.server_type = st.stype - mgr.server_cls = st - break + server_types = mgr.server_types = kwargs['server_types'] + + if server_types is None: + from pgadmin.browser.server_groups.servers.types import ServerType + server_types = ServerType.types() + + for st in server_types: + if st.instanceOf(mgr.ver): + mgr.server_type = st.stype + mgr.server_cls = st + break - mgr._update_password(encpass) mgr.update_session() return True, None def __cursor(self, server_cursor=False): - if not self.conn: + if self.wasConnected is False: raise ConnectionLost( self.manager.sid, self.db, @@ -439,14 +491,20 @@ Connection to database server (#{server_id}) for the connection - '{conn_id}' ha ) ) - if self.auto_reconnect: - status, errmsg = self.connect() + if self.auto_reconnect and not self.reconnecting: + self.reconnecting = True + try: + status, errmsg = self.connect() + except Exception as e: + current_app.logger.exception(e) + finally: + self.reconnecting = False if not status: errmsg = gettext( - """ -Attempt to reconnect failed with the error: -{0}""".format(errmsg) + "Attempt to reconnect failed with the error:\n{0}".format( + errmsg + ) ) if not status: @@ -464,6 +522,7 @@ Attempt to reconnect failed with the error: else: cur = self.conn.cursor(cursor_factory=DictCursor) except psycopg2.Error as pe: + current_app.logger.exception(pe) errmsg = gettext(""" Failed to create cursor for psycopg2 connection with error message for the \ server#{1}:{2}: @@ -472,7 +531,7 @@ server#{1}:{2}: self.conn.close() self.conn = None - if self.auto_reconnect: + if self.auto_reconnect and not self.reconnecting: current_app.logger.debug(""" Attempting to reconnect to the database server (#{server_id}) for the connection - '{conn_id}'. """.format( @@ -480,7 +539,11 @@ Attempting to reconnect to the database server (#{server_id}) for the connection conn_id=self.conn_id ) ) - status, cur = self.connect() + self.reconnecting = True + try: + status, cur = self.connect() + finally: + self.reconnecting = False if not status: msg = gettext( u""" @@ -537,7 +600,7 @@ Attempt to reconnect it failed with the error: cur.close() errmsg = self._formatted_exception_msg(pe, formatted_exception_msg) current_app.logger.error( - u"Failed to execute query ((with server cursor) for the server #{server_id} - {conn_id} (Query-id: {query_id}):\nError Message:{errmsg}".format( + u"failed to execute query ((with server cursor) for the server #{server_id} - {conn_id} (query-id: {query_id}):\nerror message:{errmsg}".format( server_id=self.manager.sid, conn_id=self.conn_id, query=query, @@ -606,6 +669,10 @@ Attempt to reconnect it failed with the error: except psycopg2.Error as pe: cur.close() if not self.connected(): + if self.auto_reconnect and not self.reconnecting: + return self.__attempt_execution_reconnect( + self.execute_dict, query, params, formatted_exception_msg + ) raise ConnectionLost( self.manager.sid, self.db, @@ -713,6 +780,10 @@ Failed to execute query (execute_async) for the server #{server_id} - {conn_id} except psycopg2.Error as pe: cur.close() if not self.connected(): + if self.auto_reconnect and not self.reconnecting: + return self.__attempt_execution_reconnect( + self.execute_void, query, params, formatted_exception_msg + ) raise ConnectionLost( self.manager.sid, self.db, @@ -736,6 +807,35 @@ Failed to execute query (execute_void) for the server #{server_id} - {conn_id} return True, None + def __attempt_execution_reconnect(self, fn, *args, **kwargs): + self.reconnecting = True + setattr(g, "{0}#{1}".format( + self.manager.sid, + self.conn_id.encode('utf-8') + ), None) + try: + status, msg = self.connect() + if status: + status, res = fn(*args, **kwargs) + self.reconnecting = False + return status, res + except Exception as e: + current_app.logger.exception(e) + self.reconnecting = False + + current_app.warning( + "Failed to reconnect the database server (#{server_id})".format( + server_id=self.manager.sid, + conn_id=self.conn_id + ) + ) + self.reconnecting = False + raise ConnectionLost( + self.manager.sid, + self.db, + None if self.conn_id[0:3] == u'DB:' else self.conn_id[5:] + ) + def execute_2darray(self, query, params=None, formatted_exception_msg=False): status, cur = self.__cursor() self.row_count = 0 @@ -758,11 +858,11 @@ Failed to execute query (execute_void) for the server #{server_id} - {conn_id} except psycopg2.Error as pe: cur.close() if not self.connected(): - raise ConnectionLost( - self.manager.sid, - self.db, - None if self.conn_id[0:3] == u'DB:' else self.conn_id[5:] - ) + if self.wasConnected and self.auto_reconnect and \ + not self.reconnecting: + return self.__attempt_execution_reconnect( + self.execute_2darray, query, params, formatted_exception_msg + ) errmsg = self._formatted_exception_msg(pe, formatted_exception_msg) current_app.logger.error( u"Failed to execute query (execute_2darray) for the server #{server_id} - {conn_id} (Query-id: {query_id}):\nError Message:{errmsg}".format( @@ -809,6 +909,11 @@ Failed to execute query (execute_void) for the server #{server_id} - {conn_id} except psycopg2.Error as pe: cur.close() if not self.connected(): + if self.auto_reconnect and not self.reconnecting: + return self.__attempt_execution_reconnect( + self.execute_dict, query, params, + formatted_exception_msg + ) raise ConnectionLost( self.manager.sid, self.db, @@ -900,10 +1005,12 @@ Failed to reset the connection to the server due to following error: return self.execute_scalar('SELECT 1') def _release(self): - if self.conn: - self.conn.close() - self.conn = None + if self.wasConneted: + if self.conn: + self.conn.close() + self.conn = None self.password = None + self.wasConnected = False def _wait(self, conn): """ @@ -1227,6 +1334,7 @@ class ServerManager(object): self.ssl_mode = server.ssl_mode self.pinged = datetime.datetime.now() self.db_info = dict() + self.server_types = None for con in self.connections: self.connections[con]._release() @@ -1430,7 +1538,7 @@ WHERE db.oid = {0}""".format(did)) self.password = passwd for conn_id in self.connections: conn = self.connections[conn_id] - if conn.conn is not None: + if conn.conn is not None or conn.wasConnected is True: conn.password = passwd def update_session(self): ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: RM#1387 [Add-on PATCH] Bad handling of missing connection database server @ 2016-08-30 16:05 Ashesh Vashi <[email protected]> parent: Ashesh Vashi <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Ashesh Vashi @ 2016-08-30 16:05 UTC (permalink / raw) To: Dave Page <[email protected]>; +Cc: pgadmin-hackers On Tue, Aug 30, 2016 at 7:16 PM, Ashesh Vashi <[email protected] > wrote: > Hi Dave, > > Please find the add-on patch on top of the current change. > > Can you please take a look at it? > This mainly works on the postgres driver to make an attempt to reconnect > the server. > One more attempt with some more corner cases handling. * Handled the connection-lost, and object gone error on client side during 'refresh' operation. * Handle the reconnection more consistently (even during cursor object creation). Please take a look at it. -- Thanks & Regards, Ashesh Vashi EnterpriseDB INDIA: Enterprise PostgreSQL Company <http://www.enterprisedb.com/; *http://www.linkedin.com/in/asheshvashi* <http://www.linkedin.com/in/asheshvashi; > > -- > > Thanks & Regards, > > Ashesh Vashi > EnterpriseDB INDIA: Enterprise PostgreSQL Company > <http://www.enterprisedb.com; > > > *http://www.linkedin.com/in/asheshvashi* > <http://www.linkedin.com/in/asheshvashi; > -- Sent via pgadmin-hackers mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgadmin-hackers Attachments: [application/octet-stream] RM1387_addon_v2.patch (23.6K, 3-RM1387_addon_v2.patch) download | inline diff: diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py index 4271199..0b6c6ca 100644 --- a/web/pgadmin/browser/server_groups/servers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/__init__.py @@ -818,7 +818,7 @@ class ServerNode(PGChildNodeView): 'servers/password.html', server_label=server.name, username=server.username, - errmsg=e.message if e.message else str(e), + errmsg=getattr(e, 'message', str(e)), _=gettext ) ) diff --git a/web/pgadmin/browser/templates/browser/js/browser.js b/web/pgadmin/browser/templates/browser/js/browser.js index 0dbce17..965bbae 100644 --- a/web/pgadmin/browser/templates/browser/js/browser.js +++ b/web/pgadmin/browser/templates/browser/js/browser.js @@ -8,7 +8,7 @@ define('pgadmin.browser', 'pgadmin.browser.node', 'pgadmin.browser.collection' ], -function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) { +function(require, $, _, S, Bootstrap, pgAdmin, Alertify, CodeMirror) { // Some scripts do export their object in the window only. // Generally the one, which do no have AMD support. @@ -40,6 +40,7 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) { _.each(data, function(d){ d._label = d.label; d.label = _.escape(d.label); + data._inode = data.inode; }) return data; }; @@ -991,6 +992,7 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) { } _data._label = _data.label; _data.label = _.escape(_data.label); + _data._inode = _data.inode; traversePath(); }, @@ -1321,6 +1323,7 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) { ctx.pI.push(_old); _new._label = _new.label; _new.label = _.escape(_new.label); + _new._inode = _new.inode; if (_old._pid != _new._pid) { ctx.op = 'RECREATE'; @@ -1351,7 +1354,7 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) { ctx.i = null; ctx.d = null; } else { - isOpen = this.tree.isInode(_i) && this.tree.isOpen(_i); + isOpen = (this.tree.isInode(_i) && this.tree.isOpen(_i)); } ctx.branch = ctx.t.serialize( @@ -1383,7 +1386,8 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) { return; } var fetchNodeInfo = function(_i, _d, _n) { - var url = _n.generate_url(_i, 'nodes', _d, true); + var info = _n.getTreeNodeHierarchy(_i), + url = _n.generate_url(_i, 'nodes', _d, true); $.ajax({ url: url, @@ -1396,6 +1400,7 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) { data._label = data.label; data.label = _.escape(data.label); + data._inode = data.inode; var d = ctx.t.itemData(ctx.i); _.extend(d, data); ctx.t.setLabel(ctx.i, {label: _d.label}); @@ -1417,21 +1422,44 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) { } }, error: function(jqx, error, status) { - var p = ctx.t.parent(ctx.i); - - if (!p) - return; - - ctx.t.remove(ctx.i, { - success: function() { - // Try to refresh the parent on error - try { - pgBrowser.Events.trigger( - 'pgadmin:browser:tree:refresh', p - ); - } catch(e) {} + if ( + !Alertify.pgHandleItemError( + xhr, error, message, {item: _i, info: info} + ) + ) { + var msg = xhr.responseText, + contentType = xhr.getResponseHeader('Content-Type'), + msg = xhr.responseText, + jsonResp = ( + contentType && + contentType.indexOf('application/json') == 0 && + $.parseJSON(xhr.responseText) + ) || {}; + + if (xhr.status == 410 && jsonResp.success == 0) { + var p = ctx.t.parent(ctx.i); + + ctx.t.remove(ctx.i, { + success: function() { + if (p) { + // Try to refresh the parent on error + try { + pgBrowser.Events.trigger( + 'pgadmin:browser:tree:refresh', p + ); + } catch(e) {} + } + } + }); } - }); + + Alertify.pgNotifier( + error, xhr, "{{ _("Error retrieving details for the node.") }}", + function() { + console.log(arguments); + } + ); + } } }); }.bind(this); @@ -1466,6 +1494,13 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) { console.log(arguments); } }); + } else if (!this.tree.isInode(_i) && d._inode) { + this.tree.setInode(_i, { + success: fetchNodeInfo.bind(this, _i, d, n), + fail: function() { + console.log(arguments); + } + }); } else { fetchNodeInfo(_i, d, n); } diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py index e3a9e96..d745fee 100644 --- a/web/pgadmin/utils/driver/psycopg2/__init__.py +++ b/web/pgadmin/utils/driver/psycopg2/__init__.py @@ -131,6 +131,9 @@ class Connection(BaseConnection): * _release() - Release the connection object of psycopg2 + * _reconnect() + - Attempt to reconnect to the database + * _wait(conn) - This method is used to wait for asynchronous connection. This is a blocking call. @@ -181,6 +184,8 @@ class Connection(BaseConnection): self.row_count = 0 self.__notices = None self.password = None + self.wasConnected = False + self.reconnecting = False super(Connection, self).__init__() @@ -233,7 +238,8 @@ class Connection(BaseConnection): encpass = self.password or getattr(mgr, 'password', None) # Reset the existing connection password - self.password = None + if self.reconnecting is not False: + self.password = None if encpass: # Fetch Logged in User Details. @@ -301,8 +307,44 @@ Failed to connect to the database server(#{server_id}) for connection ({conn_id} return False, msg self.conn = pg_conn - self.__backend_pid = pg_conn.get_backend_pid() + self.wasConnected = True + try: + status, msg = self._initialize(conn_id, **kwargs) + except Exception as e: + current_app.logger.exception(e) + self.conn = None + if not self.reconnecting: + self.wasConnected = False + raise e + + if status: + mgr._update_password(encpass) + else: + if not self.reconnecting: + self.wasConnected = False + + return status, msg + + def _initialize(self, conn_id, **kwargs): self.execution_aborted = False + self.__backend_pid = self.conn.get_backend_pid() + + setattr(g, "{0}#{1}".format( + self.manager.sid, + self.conn_id.encode('utf-8') + ), None) + + status, cur = self.__cursor() + formatted_exception_msg = self._formatted_exception_msg + mgr = self.manager + + def _execute(cur, query, params=None): + try: + self.__internal_blocking_execute(cur, query, params) + except psycopg2.Error as pe: + cur.close() + return formatted_exception_msg(pe, False) + return None # autocommit flag does not work with asynchronous connections. # By default asynchronous connection runs in autocommit mode. @@ -313,22 +355,22 @@ Failed to connect to the database server(#{server_id}) for connection ({conn_id} self.conn.autocommit = True register_date_typecasters(self.conn) - status, res = self.execute_scalar(""" + status = _execute(cur, """ SET DateStyle=ISO; SET client_min_messages=notice; SET bytea_output=escape; SET client_encoding='UNICODE';""") - if not status: + if status is not None: self.conn.close() self.conn = None - return False, res + return False, status if mgr.role: - status, res = self.execute_scalar(u"SET ROLE TO %s", [mgr.role]) + status = _execute(cur, u"SET ROLE TO %s", [mgr.role]) - if not status: + if status is not None: self.conn.close() self.conn = None current_app.logger.error(""" @@ -337,35 +379,38 @@ Connect to the database server (#{server_id}) for connection ({conn_id}), but - """.format( server_id=self.manager.sid, conn_id=conn_id, - msg=res + msg=status ) ) return False, \ _("Failed to setup the role with error message:\n{0}").format( - res + status ) if mgr.ver is None: - status, res = self.execute_scalar("SELECT version()") + status = _execute(cur, "SELECT version()") - if status: - mgr.ver = res - mgr.sversion = pg_conn.server_version - else: + if status is not None: self.conn.close() self.conn = None + self.wasConneted = False current_app.logger.error(""" Failed to fetch the version information on the established connection to the database server (#{server_id}) for '{conn_id}' with below error message: {msg} """.format( server_id=self.manager.sid, conn_id=conn_id, - msg=res + msg=status ) ) - return False, res + return False, status + + if cur.rowcount > 0: + row = cur.fetchmany(1)[0] + mgr.ver = row['version'] + mgr.sversion = self.conn.server_version - status, res = self.execute_dict(""" + status = _execute(cur, """ SELECT db.oid as did, db.datname, db.datallowconn, pg_encoding_to_char(db.encoding) AS serverencoding, has_database_privilege(db.oid, 'CREATE') as cancreate, datlastsysoid @@ -373,16 +418,17 @@ FROM pg_database db WHERE db.datname = current_database()""") - if status: + if status is None: mgr.db_info = mgr.db_info or dict() - f_row = res['rows'][0] - mgr.db_info[f_row['did']] = f_row.copy() + if cur.rowcount > 0: + res = cur.fetchmany(1)[0] + mgr.db_info[res['did']] = res.copy() - # We do not have database oid for the maintenance database. - if len(mgr.db_info) == 1: - mgr.did = f_row['did'] + # We do not have database oid for the maintenance database. + if len(mgr.db_info) == 1: + mgr.did = res['did'] - status, res = self.execute_dict(""" + status = _execute(cur, """ SELECT oid as id, rolname as name, rolsuper as is_superuser, rolcreaterole as can_create_role, rolcreatedb as can_create_db @@ -391,28 +437,34 @@ FROM WHERE rolname = current_user""") - if status: + if status is None: mgr.user_info = dict() - f_row = res['rows'][0] - mgr.user_info = f_row.copy() + if cur.rowcount > 0: + mgr.user_info = cur.fetchmany(1)[0] if 'password' in kwargs: mgr.password = kwargs['password'] + server_types = None if 'server_types' in kwargs and isinstance(kwargs['server_types'], list): - for st in kwargs['server_types']: - if st.instanceOf(mgr.ver): - mgr.server_type = st.stype - mgr.server_cls = st - break + server_types = mgr.server_types = kwargs['server_types'] + + if server_types is None: + from pgadmin.browser.server_groups.servers.types import ServerType + server_types = ServerType.types() + + for st in server_types: + if st.instanceOf(mgr.ver): + mgr.server_type = st.stype + mgr.server_cls = st + break - mgr._update_password(encpass) mgr.update_session() return True, None def __cursor(self, server_cursor=False): - if not self.conn: + if self.wasConnected is False: raise ConnectionLost( self.manager.sid, self.db, @@ -428,73 +480,68 @@ WHERE return True, cur if not self.connected(): - status = False errmsg = "" - current_app.logger.warning(""" -Connection to database server (#{server_id}) for the connection - '{conn_id}' has been lost. -""".format( - server_id=self.manager.sid, - conn_id=self.conn_id - ) + current_app.logger.warning( + "Connection to database server (#{server_id}) for the connection - '{conn_id}' has been lost.".format( + server_id=self.manager.sid, + conn_id=self.conn_id + ) ) - if self.auto_reconnect: - status, errmsg = self.connect() - - if not status: - errmsg = gettext( - """ -Attempt to reconnect failed with the error: -{0}""".format(errmsg) - ) - - if not status: - msg = gettext("Connection lost.\n{0}").format(errmsg) - current_app.logger.error(errmsg) - - return False, msg + if self.auto_reconnect and not self.reconnecting: + self.__attempt_execution_reconnect(None) + else: + raise ConnectionLost( + self.manager.sid, + self.db, + None if self.conn_id[0:3] == u'DB:' else self.conn_id[5:] + ) try: if server_cursor: # Providing name to cursor will create server side cursor. cursor_name = "CURSOR:{0}".format(self.conn_id) - cur = self.conn.cursor(name=cursor_name, - cursor_factory=DictCursor) + cur = self.conn.cursor( + name=cursor_name, cursor_factory=DictCursor + ) else: cur = self.conn.cursor(cursor_factory=DictCursor) except psycopg2.Error as pe: - errmsg = gettext(""" -Failed to create cursor for psycopg2 connection with error message for the \ -server#{1}:{2}: -{0}""").format(str(pe), self.manager.sid, self.db) - current_app.logger.error(errmsg) - self.conn.close() - self.conn = None + current_app.logger.exception(pe) + errmsg = gettext( + "Failed to create cursor for psycopg2 connection with error message for the server#{1}:{2}:\n{0}" + ).format( + str(pe), self.manager.sid, self.db + ) - if self.auto_reconnect: - current_app.logger.debug(""" -Attempting to reconnect to the database server (#{server_id}) for the connection - '{conn_id}'. -""".format( - server_id=self.manager.sid, - conn_id=self.conn_id - ) - ) - status, cur = self.connect() - if not status: - msg = gettext( - u""" -Connection for server#{0} with database "{1}" was lost. -Attempt to reconnect it failed with the error: -{2}""" - ).format(self.driver.server_id, self.db, cur) - current_app.logger.error(msg) - - return False, cur - else: - return False, errmsg + current_app.logger.error(errmsg) + if self.conn.closed: + self.conn = None + if self.auto_reconnect and not self.reconnecting: + current_app.logger.info( + gettext( + "Attempting to reconnect to the database server (#{server_id}) for the connection - '{conn_id}'." + ).format( + server_id=self.manager.sid, + conn_id=self.conn_id + ) + ) + return self.__attempt_execution_reconnect( + self.__cursor, server_cursor + ) + else: + raise ConnectionLost( + self.manager.sid, + self.db, + None if self.conn_id[0:3] == u'DB:' else self.conn_id[5:] + ) - setattr(g, "{0}#{1}".format(self.manager.sid, self.conn_id.encode('utf-8')), cur) + setattr( + g, "{0}#{1}".format( + self.manager.sid, self.conn_id.encode('utf-8') + ), cur + ) return True, cur @@ -537,7 +584,7 @@ Attempt to reconnect it failed with the error: cur.close() errmsg = self._formatted_exception_msg(pe, formatted_exception_msg) current_app.logger.error( - u"Failed to execute query ((with server cursor) for the server #{server_id} - {conn_id} (Query-id: {query_id}):\nError Message:{errmsg}".format( + u"failed to execute query ((with server cursor) for the server #{server_id} - {conn_id} (query-id: {query_id}):\nerror message:{errmsg}".format( server_id=self.manager.sid, conn_id=self.conn_id, query=query, @@ -606,6 +653,10 @@ Attempt to reconnect it failed with the error: except psycopg2.Error as pe: cur.close() if not self.connected(): + if self.auto_reconnect and not self.reconnecting: + return self.__attempt_execution_reconnect( + self.execute_dict, query, params, formatted_exception_msg + ) raise ConnectionLost( self.manager.sid, self.db, @@ -713,6 +764,10 @@ Failed to execute query (execute_async) for the server #{server_id} - {conn_id} except psycopg2.Error as pe: cur.close() if not self.connected(): + if self.auto_reconnect and not self.reconnecting: + return self.__attempt_execution_reconnect( + self.execute_void, query, params, formatted_exception_msg + ) raise ConnectionLost( self.manager.sid, self.db, @@ -736,6 +791,36 @@ Failed to execute query (execute_void) for the server #{server_id} - {conn_id} return True, None + def __attempt_execution_reconnect(self, fn, *args, **kwargs): + self.reconnecting = True + setattr(g, "{0}#{1}".format( + self.manager.sid, + self.conn_id.encode('utf-8') + ), None) + try: + status, res = self.connect() + if status: + if fn: + status, res = fn(*args, **kwargs) + self.reconnecting = False + return status, res + except Exception as e: + current_app.logger.exception(e) + self.reconnecting = False + + current_app.warning( + "Failed to reconnect the database server (#{server_id})".format( + server_id=self.manager.sid, + conn_id=self.conn_id + ) + ) + self.reconnecting = False + raise ConnectionLost( + self.manager.sid, + self.db, + None if self.conn_id[0:3] == u'DB:' else self.conn_id[5:] + ) + def execute_2darray(self, query, params=None, formatted_exception_msg=False): status, cur = self.__cursor() self.row_count = 0 @@ -758,11 +843,11 @@ Failed to execute query (execute_void) for the server #{server_id} - {conn_id} except psycopg2.Error as pe: cur.close() if not self.connected(): - raise ConnectionLost( - self.manager.sid, - self.db, - None if self.conn_id[0:3] == u'DB:' else self.conn_id[5:] - ) + if self.wasConnected and self.auto_reconnect and \ + not self.reconnecting: + return self.__attempt_execution_reconnect( + self.execute_2darray, query, params, formatted_exception_msg + ) errmsg = self._formatted_exception_msg(pe, formatted_exception_msg) current_app.logger.error( u"Failed to execute query (execute_2darray) for the server #{server_id} - {conn_id} (Query-id: {query_id}):\nError Message:{errmsg}".format( @@ -809,6 +894,11 @@ Failed to execute query (execute_void) for the server #{server_id} - {conn_id} except psycopg2.Error as pe: cur.close() if not self.connected(): + if self.auto_reconnect and not self.reconnecting: + return self.__attempt_execution_reconnect( + self.execute_dict, query, params, + formatted_exception_msg + ) raise ConnectionLost( self.manager.sid, self.db, @@ -900,10 +990,12 @@ Failed to reset the connection to the server due to following error: return self.execute_scalar('SELECT 1') def _release(self): - if self.conn: - self.conn.close() - self.conn = None + if self.wasConneted: + if self.conn: + self.conn.close() + self.conn = None self.password = None + self.wasConnected = False def _wait(self, conn): """ @@ -1227,6 +1319,7 @@ class ServerManager(object): self.ssl_mode = server.ssl_mode self.pinged = datetime.datetime.now() self.db_info = dict() + self.server_types = None for con in self.connections: self.connections[con]._release() @@ -1430,7 +1523,7 @@ WHERE db.oid = {0}""".format(did)) self.password = passwd for conn_id in self.connections: conn = self.connections[conn_id] - if conn.conn is not None: + if conn.conn is not None or conn.wasConnected is True: conn.password = passwd def update_session(self): ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: RM#1387 [Add-on PATCH] Bad handling of missing connection database server @ 2016-09-02 14:19 Dave Page <[email protected]> parent: Ashesh Vashi <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Dave Page @ 2016-09-02 14:19 UTC (permalink / raw) To: Ashesh Vashi <[email protected]>; +Cc: pgadmin-hackers; Akshay Joshi <[email protected]> Akshay, can you review/commit this please? Thanks. On Tue, Aug 30, 2016 at 5:05 PM, Ashesh Vashi <[email protected] > wrote: > On Tue, Aug 30, 2016 at 7:16 PM, Ashesh Vashi < > [email protected]> wrote: > >> Hi Dave, >> >> Please find the add-on patch on top of the current change. >> >> Can you please take a look at it? >> This mainly works on the postgres driver to make an attempt to reconnect >> the server. >> > > One more attempt with some more corner cases handling. > * Handled the connection-lost, and object gone error on client side during > 'refresh' operation. > * Handle the reconnection more consistently (even during cursor object > creation). > > Please take a look at it. > > -- > > Thanks & Regards, > > Ashesh Vashi > EnterpriseDB INDIA: Enterprise PostgreSQL Company > <http://www.enterprisedb.com/; > > > *http://www.linkedin.com/in/asheshvashi* > <http://www.linkedin.com/in/asheshvashi; > >> >> -- >> >> Thanks & Regards, >> >> Ashesh Vashi >> EnterpriseDB INDIA: Enterprise PostgreSQL Company >> <http://www.enterprisedb.com; >> >> >> *http://www.linkedin.com/in/asheshvashi* >> <http://www.linkedin.com/in/asheshvashi; >> > > -- Dave Page Blog: http://pgsnake.blogspot.com Twitter: @pgsnake EnterpriseDB UK: http://www.enterprisedb.com The Enterprise PostgreSQL Company ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: RM#1387 [Add-on PATCH] Bad handling of missing connection database server @ 2016-09-06 06:35 Akshay Joshi <[email protected]> parent: Dave Page <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Akshay Joshi @ 2016-09-06 06:35 UTC (permalink / raw) To: Dave Page <[email protected]>; +Cc: Ashesh Vashi <[email protected]>; pgadmin-hackers On Fri, Sep 2, 2016 at 7:49 PM, Dave Page <[email protected]> wrote: > Akshay, can you review/commit this please? > Sure. > > Thanks. > > On Tue, Aug 30, 2016 at 5:05 PM, Ashesh Vashi < > [email protected]> wrote: > >> On Tue, Aug 30, 2016 at 7:16 PM, Ashesh Vashi < >> [email protected]> wrote: >> >>> Hi Dave, >>> >>> Please find the add-on patch on top of the current change. >>> >>> Can you please take a look at it? >>> This mainly works on the postgres driver to make an attempt to reconnect >>> the server. >>> >> >> One more attempt with some more corner cases handling. >> * Handled the connection-lost, and object gone error on client side >> during 'refresh' operation. >> * Handle the reconnection more consistently (even during cursor object >> creation). >> >> Please take a look at it. >> >> -- >> >> Thanks & Regards, >> >> Ashesh Vashi >> EnterpriseDB INDIA: Enterprise PostgreSQL Company >> <http://www.enterprisedb.com/; >> >> >> *http://www.linkedin.com/in/asheshvashi* >> <http://www.linkedin.com/in/asheshvashi; >> >>> >>> -- >>> >>> Thanks & Regards, >>> >>> Ashesh Vashi >>> EnterpriseDB INDIA: Enterprise PostgreSQL Company >>> <http://www.enterprisedb.com; >>> >>> >>> *http://www.linkedin.com/in/asheshvashi* >>> <http://www.linkedin.com/in/asheshvashi; >>> >> >> > > > -- > Dave Page > Blog: http://pgsnake.blogspot.com > Twitter: @pgsnake > > EnterpriseDB UK: http://www.enterprisedb.com > The Enterprise PostgreSQL Company > -- *Akshay Joshi* *Principal Software Engineer * *Phone: +91 20-3058-9517Mobile: +91 976-788-8246* ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: RM#1387 [Add-on PATCH] Bad handling of missing connection database server @ 2016-09-06 13:05 Akshay Joshi <[email protected]> parent: Akshay Joshi <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Akshay Joshi @ 2016-09-06 13:05 UTC (permalink / raw) To: Dave Page <[email protected]>; +Cc: Ashesh Vashi <[email protected]>; pgadmin-hackers Code looks good to me. Patch applied. On Tue, Sep 6, 2016 at 12:05 PM, Akshay Joshi <[email protected] > wrote: > > > On Fri, Sep 2, 2016 at 7:49 PM, Dave Page <[email protected]> wrote: > >> Akshay, can you review/commit this please? >> > > Sure. > >> >> Thanks. >> >> On Tue, Aug 30, 2016 at 5:05 PM, Ashesh Vashi < >> [email protected]> wrote: >> >>> On Tue, Aug 30, 2016 at 7:16 PM, Ashesh Vashi < >>> [email protected]> wrote: >>> >>>> Hi Dave, >>>> >>>> Please find the add-on patch on top of the current change. >>>> >>>> Can you please take a look at it? >>>> This mainly works on the postgres driver to make an attempt to >>>> reconnect the server. >>>> >>> >>> One more attempt with some more corner cases handling. >>> * Handled the connection-lost, and object gone error on client side >>> during 'refresh' operation. >>> * Handle the reconnection more consistently (even during cursor object >>> creation). >>> >>> Please take a look at it. >>> >>> -- >>> >>> Thanks & Regards, >>> >>> Ashesh Vashi >>> EnterpriseDB INDIA: Enterprise PostgreSQL Company >>> <http://www.enterprisedb.com/; >>> >>> >>> *http://www.linkedin.com/in/asheshvashi* >>> <http://www.linkedin.com/in/asheshvashi; >>> >>>> >>>> -- >>>> >>>> Thanks & Regards, >>>> >>>> Ashesh Vashi >>>> EnterpriseDB INDIA: Enterprise PostgreSQL Company >>>> <http://www.enterprisedb.com; >>>> >>>> >>>> *http://www.linkedin.com/in/asheshvashi* >>>> <http://www.linkedin.com/in/asheshvashi; >>>> >>> >>> >> >> >> -- >> Dave Page >> Blog: http://pgsnake.blogspot.com >> Twitter: @pgsnake >> >> EnterpriseDB UK: http://www.enterprisedb.com >> The Enterprise PostgreSQL Company >> > > > > -- > *Akshay Joshi* > *Principal Software Engineer * > > > > *Phone: +91 20-3058-9517Mobile: +91 976-788-8246* > -- *Akshay Joshi* *Principal Software Engineer * *Phone: +91 20-3058-9517Mobile: +91 976-788-8246* ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: Re: RM#1387 [Add-on PATCH] Bad handling of missing connection database server @ 2016-09-07 11:38 Surinder Kumar <[email protected]> parent: Akshay Joshi <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Surinder Kumar @ 2016-09-07 11:38 UTC (permalink / raw) To: Akshay Joshi <[email protected]>; +Cc: Dave Page <[email protected]>; Ashesh Vashi <[email protected]>; pgadmin-hackers Hi while closing query tool, the following error is display on python console. File "/Users/surinder/Documents/Projects/pgadmin4/web/pgadmin/tools/datagrid/__init__.py", line 270, in close manager.release(did=cmd_obj.did, conn_id=cmd_obj.conn_id) File "/Users/surinder/Documents/Projects/pgadmin4/web/pgadmin/utils/driver/psycopg2/__init__.py", line 1501, in release self.connections[my_id]._release() File "/Users/surinder/Documents/Projects/pgadmin4/web/pgadmin/utils/driver/psycopg2/__init__.py", line 1002, in _release if self.wasConneted: AttributeError: 'Connection' object has no attribute 'wasConneted' *Issue:* This issue is due to typo. Please find attached patch. On Tue, Sep 6, 2016 at 6:35 PM, Akshay Joshi <[email protected]> wrote: > Code looks good to me. Patch applied. > > On Tue, Sep 6, 2016 at 12:05 PM, Akshay Joshi < > [email protected]> wrote: > >> >> >> On Fri, Sep 2, 2016 at 7:49 PM, Dave Page <[email protected]> wrote: >> >>> Akshay, can you review/commit this please? >>> >> >> Sure. >> >>> >>> Thanks. >>> >>> On Tue, Aug 30, 2016 at 5:05 PM, Ashesh Vashi < >>> [email protected]> wrote: >>> >>>> On Tue, Aug 30, 2016 at 7:16 PM, Ashesh Vashi < >>>> [email protected]> wrote: >>>> >>>>> Hi Dave, >>>>> >>>>> Please find the add-on patch on top of the current change. >>>>> >>>>> Can you please take a look at it? >>>>> This mainly works on the postgres driver to make an attempt to >>>>> reconnect the server. >>>>> >>>> >>>> One more attempt with some more corner cases handling. >>>> * Handled the connection-lost, and object gone error on client side >>>> during 'refresh' operation. >>>> * Handle the reconnection more consistently (even during cursor object >>>> creation). >>>> >>>> Please take a look at it. >>>> >>>> -- >>>> >>>> Thanks & Regards, >>>> >>>> Ashesh Vashi >>>> EnterpriseDB INDIA: Enterprise PostgreSQL Company >>>> <http://www.enterprisedb.com/; >>>> >>>> >>>> *http://www.linkedin.com/in/asheshvashi* >>>> <http://www.linkedin.com/in/asheshvashi; >>>> >>>>> >>>>> -- >>>>> >>>>> Thanks & Regards, >>>>> >>>>> Ashesh Vashi >>>>> EnterpriseDB INDIA: Enterprise PostgreSQL Company >>>>> <http://www.enterprisedb.com; >>>>> >>>>> >>>>> *http://www.linkedin.com/in/asheshvashi* >>>>> <http://www.linkedin.com/in/asheshvashi; >>>>> >>>> >>>> >>> >>> >>> -- >>> Dave Page >>> Blog: http://pgsnake.blogspot.com >>> Twitter: @pgsnake >>> >>> EnterpriseDB UK: http://www.enterprisedb.com >>> The Enterprise PostgreSQL Company >>> >> >> >> >> -- >> *Akshay Joshi* >> *Principal Software Engineer * >> >> >> >> *Phone: +91 20-3058-9517Mobile: +91 976-788-8246* >> > > > > -- > *Akshay Joshi* > *Principal Software Engineer * > > > > *Phone: +91 20-3058-9517Mobile: +91 976-788-8246* > -- Sent via pgadmin-hackers mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgadmin-hackers Attachments: [application/octet-stream] fix_typo_in_pyscopg2_driver.patch (1.0K, 3-fix_typo_in_pyscopg2_driver.patch) download | inline diff: diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py index 9116aea..d4465ea 100644 --- a/web/pgadmin/utils/driver/psycopg2/__init__.py +++ b/web/pgadmin/utils/driver/psycopg2/__init__.py @@ -402,7 +402,7 @@ Connect to the database server (#{server_id}) for connection ({conn_id}), but - if status is not None: self.conn.close() self.conn = None - self.wasConneted = False + self.wasConnected = False current_app.logger.error(""" Failed to fetch the version information on the established connection to the database server (#{server_id}) for '{conn_id}' with below error message: {msg} @@ -999,7 +999,7 @@ Failed to reset the connection to the server due to following error: return self.execute_scalar('SELECT 1') def _release(self): - if self.wasConneted: + if self.wasConnected: if self.conn: self.conn.close() self.conn = None ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: Re: RM#1387 [Add-on PATCH] Bad handling of missing connection database server @ 2016-09-07 13:02 Dave Page <[email protected]> parent: Surinder Kumar <[email protected]> 0 siblings, 0 replies; 7+ messages in thread From: Dave Page @ 2016-09-07 13:02 UTC (permalink / raw) To: Surinder Kumar <[email protected]>; +Cc: Akshay Joshi <[email protected]>; Ashesh Vashi <[email protected]>; pgadmin-hackers Thanks - applied. On Wed, Sep 7, 2016 at 12:38 PM, Surinder Kumar < [email protected]> wrote: > Hi > > while closing query tool, the following error is display on python console. > > File "/Users/surinder/Documents/Projects/pgadmin4/web/pgadmin/tools/datagrid/__init__.py", > line 270, in close > manager.release(did=cmd_obj.did, conn_id=cmd_obj.conn_id) > File "/Users/surinder/Documents/Projects/pgadmin4/web/pgadmin/ > utils/driver/psycopg2/__init__.py", line 1501, in release > self.connections[my_id]._release() > File "/Users/surinder/Documents/Projects/pgadmin4/web/pgadmin/ > utils/driver/psycopg2/__init__.py", line 1002, in _release > if self.wasConneted: > AttributeError: 'Connection' object has no attribute 'wasConneted' > > *Issue:* > This issue is due to typo. Please find attached patch. > > On Tue, Sep 6, 2016 at 6:35 PM, Akshay Joshi < > [email protected]> wrote: > >> Code looks good to me. Patch applied. >> >> On Tue, Sep 6, 2016 at 12:05 PM, Akshay Joshi < >> [email protected]> wrote: >> >>> >>> >>> On Fri, Sep 2, 2016 at 7:49 PM, Dave Page <[email protected]> wrote: >>> >>>> Akshay, can you review/commit this please? >>>> >>> >>> Sure. >>> >>>> >>>> Thanks. >>>> >>>> On Tue, Aug 30, 2016 at 5:05 PM, Ashesh Vashi < >>>> [email protected]> wrote: >>>> >>>>> On Tue, Aug 30, 2016 at 7:16 PM, Ashesh Vashi < >>>>> [email protected]> wrote: >>>>> >>>>>> Hi Dave, >>>>>> >>>>>> Please find the add-on patch on top of the current change. >>>>>> >>>>>> Can you please take a look at it? >>>>>> This mainly works on the postgres driver to make an attempt to >>>>>> reconnect the server. >>>>>> >>>>> >>>>> One more attempt with some more corner cases handling. >>>>> * Handled the connection-lost, and object gone error on client side >>>>> during 'refresh' operation. >>>>> * Handle the reconnection more consistently (even during cursor object >>>>> creation). >>>>> >>>>> Please take a look at it. >>>>> >>>>> -- >>>>> >>>>> Thanks & Regards, >>>>> >>>>> Ashesh Vashi >>>>> EnterpriseDB INDIA: Enterprise PostgreSQL Company >>>>> <http://www.enterprisedb.com/; >>>>> >>>>> >>>>> *http://www.linkedin.com/in/asheshvashi* >>>>> <http://www.linkedin.com/in/asheshvashi; >>>>> >>>>>> >>>>>> -- >>>>>> >>>>>> Thanks & Regards, >>>>>> >>>>>> Ashesh Vashi >>>>>> EnterpriseDB INDIA: Enterprise PostgreSQL Company >>>>>> <http://www.enterprisedb.com; >>>>>> >>>>>> >>>>>> *http://www.linkedin.com/in/asheshvashi* >>>>>> <http://www.linkedin.com/in/asheshvashi; >>>>>> >>>>> >>>>> >>>> >>>> >>>> -- >>>> Dave Page >>>> Blog: http://pgsnake.blogspot.com >>>> Twitter: @pgsnake >>>> >>>> EnterpriseDB UK: http://www.enterprisedb.com >>>> The Enterprise PostgreSQL Company >>>> >>> >>> >>> >>> -- >>> *Akshay Joshi* >>> *Principal Software Engineer * >>> >>> >>> >>> *Phone: +91 20-3058-9517 <%2B91%2020-3058-9517>Mobile: +91 976-788-8246* >>> >> >> >> >> -- >> *Akshay Joshi* >> *Principal Software Engineer * >> >> >> >> *Phone: +91 20-3058-9517 <%2B91%2020-3058-9517>Mobile: +91 976-788-8246* >> > > -- Dave Page Blog: http://pgsnake.blogspot.com Twitter: @pgsnake EnterpriseDB UK: http://www.enterprisedb.com The Enterprise PostgreSQL Company ^ permalink raw reply [nested|flat] 7+ messages in thread
end of thread, other threads:[~2016-09-07 13:02 UTC | newest] Thread overview: 7+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2016-08-30 13:46 RM#1387 [Add-on PATCH] Bad handling of missing connection database server Ashesh Vashi <[email protected]> 2016-08-30 16:05 ` Ashesh Vashi <[email protected]> 2016-09-02 14:19 ` Dave Page <[email protected]> 2016-09-06 06:35 ` Akshay Joshi <[email protected]> 2016-09-06 13:05 ` Akshay Joshi <[email protected]> 2016-09-07 11:38 ` Surinder Kumar <[email protected]> 2016-09-07 13:02 ` Dave Page <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox