diff --git a/web/pgadmin/browser/server_groups/servers/databases/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/__init__.py index 0328fcbd6..88360dd0c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/__init__.py @@ -134,6 +134,14 @@ class DatabaseView(PGChildNodeView): self.conn = self.manager.connection() elif 'did' in kwargs: self.conn = self.manager.connection(did=kwargs['did']) + self.db_allow_connection = True + # If connection to database is not allowed then + # provide generic connection + if kwargs['did'] in self.conn.manager.db_info: + self._db = self.conn.manager.db_info[kwargs['did']] + if self._db['datallowconn'] is False: + self.conn = self.manager.connection() + self.db_allow_connection = False else: self.conn = self.manager.connection() @@ -532,13 +540,23 @@ class DatabaseView(PGChildNodeView): request.data, encoding='utf-8' ) - conn = self.manager.connection() + # Generic connection for offline updates + conn = self.manager.connection(conn_id="db_offline_update") + status, errmsg = conn.connect() + if not status: + current_app.logger.error( + "Could not create database connection for offline updates\nErr: {0}".format( + errmsg + ) + ) + return internal_server_error(errmsg) + if did is not None: # Fetch the name of database for comparison - status, rset = conn.execute_dict( + status, rset = self.conn.execute_dict( render_template( "/".join([self.template_path, 'nodes.sql']), - did=did, conn=conn, last_system_oid=0 + did=did, conn=self.conn, last_system_oid=0 ) ) if not status: @@ -553,7 +571,10 @@ class DatabaseView(PGChildNodeView): if 'name' not in data: data['name'] = data['old_name'] - status = self.manager.release(did=did) + # Release any existing connection from connection manager + # to perform offline operation + self.manager.release(did=did) + for action in ["rename_database", "tablespace"]: SQL = self.get_offline_sql(gid, sid, data, did, action) SQL = SQL.strip('\n').strip(' ') @@ -562,20 +583,20 @@ class DatabaseView(PGChildNodeView): if not status: return internal_server_error(errormsg=msg) - if not self.manager.db_info[did]['datallowconn']: - return jsonify( - node=self.blueprint.generate_browser_node( - did, - sid, - data['name'], - "icon-database-not-connected", - connected=False, - allowConn=False - ) + # Make connection for database again + if self._db['datallowconn']: + self.conn = self.manager.connection( + database=data['name'], auto_reconnect=True ) + status, errmsg = self.conn.connect() - self.conn = self.manager.connection(database=data['name'], auto_reconnect=True) - status, errmsg = self.conn.connect() + if not status: + current_app.logger.error( + "Could not connected to database(#{0}).\nError: {1}".format( + did, errmsg + ) + ) + return internal_server_error(errmsg) SQL = self.get_online_sql(gid, sid, data, did) SQL = SQL.strip('\n').strip(' ') @@ -584,12 +605,21 @@ class DatabaseView(PGChildNodeView): if not status: return internal_server_error(errormsg=msg) + # Release any existing connection from connection manager + # used for offline updates + self.manager.release(conn_id="db_offline_update") + return jsonify( node=self.blueprint.generate_browser_node( did, sid, data['name'], - "pg-icon-{0}".format(self.node_type) + "pg-icon-{0}".format(self.node_type) if + self._db['datallowconn'] else + "icon-database-not-connected", + connected=self.conn.connected() if + self._db['datallowconn'] else False, + allowConn=self._db['datallowconn'] ) ) @@ -633,7 +663,6 @@ class DatabaseView(PGChildNodeView): return internal_server_error(errormsg=msg) - return make_json_response(success=1) @check_precondition(action="msql") @@ -687,8 +716,7 @@ class DatabaseView(PGChildNodeView): for action in ["rename_database", "tablespace"]: SQL += self.get_offline_sql(gid, sid, data, did, action) - if rset['rows'][0]['datallowconn']: - SQL += self.get_online_sql(gid, sid, data, did) + SQL += self.get_online_sql(gid, sid, data, did) else: SQL += self.get_new_sql(gid, sid, data, did) @@ -709,33 +737,30 @@ class DatabaseView(PGChildNodeView): acls = [] SQL_acl = '' - if ('datallowconn' in data and data['datallowconn']) or \ - 'datallowconn' not in data: - try: - acls = render_template( - "/".join([self.template_path, 'allowed_privs.json']) + try: + acls = render_template( + "/".join([self.template_path, 'allowed_privs.json']) + ) + acls = json.loads(acls, encoding='utf-8') + except Exception as e: + current_app.logger.exception(e) + + # Privileges + for aclcol in acls: + if aclcol in data: + allowedacl = acls[aclcol] + data[aclcol] = parse_priv_to_db( + data[aclcol], allowedacl['acl'] ) - acls = json.loads(acls, encoding='utf-8') - except Exception as e: - current_app.logger.exception(e) - # Privileges - for aclcol in acls: - if aclcol in data: - allowedacl = acls[aclcol] - data[aclcol] = parse_priv_to_db( - data[aclcol], allowedacl['acl'] - ) + SQL_acl = render_template( + "/".join([self.template_path, 'grant.sql']), + data=data, conn=self.conn + ) - SQL_acl = render_template( - "/".join([self.template_path, 'grant.sql']), - data=data, conn=self.conn - ) - - conn = self.manager.connection() SQL = render_template( "/".join([self.template_path, 'create.sql']), - data=data, conn=conn + data=data, conn=self.conn ) SQL += "\n" SQL += SQL_acl @@ -841,46 +866,44 @@ class DatabaseView(PGChildNodeView): if not status: return internal_server_error(errormsg=res) - if res['rows'][0]['datallowconn']: - SQL = render_template( - "/".join([self.template_path, 'acl.sql']), - did=did, conn=self.conn - ) - status, dataclres = self.conn.execute_dict(SQL) - if not status: - return internal_server_error(errormsg=dataclres) - res = self.formatdbacl(res, dataclres['rows']) + SQL = render_template( + "/".join([self.template_path, 'acl.sql']), + did=did, conn=self.conn + ) + status, dataclres = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=dataclres) + res = self.formatdbacl(res, dataclres['rows']) - SQL = render_template( - "/".join([self.template_path, 'defacl.sql']), - did=did, conn=self.conn - ) - status, defaclres = self.conn.execute_dict(SQL) - if not status: - return internal_server_error(errormsg=defaclres) + SQL = render_template( + "/".join([self.template_path, 'defacl.sql']), + did=did, conn=self.conn + ) + status, defaclres = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=defaclres) - res = self.formatdbacl(res, defaclres['rows']) + res = self.formatdbacl(res, defaclres['rows']) result = res['rows'][0] - if result['datallowconn']: - SQL = render_template( - "/".join([self.template_path, 'get_variables.sql']), - did=did, conn=self.conn - ) - status, res1 = self.conn.execute_dict(SQL) - if not status: - return internal_server_error(errormsg=res1) + SQL = render_template( + "/".join([self.template_path, 'get_variables.sql']), + did=did, conn=self.conn + ) + status, res1 = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res1) - # Get Formatted Security Labels - if 'seclabels' in result: - # Security Labels is not available for PostgreSQL <= 9.1 - frmtd_sec_labels = parse_sec_labels_from_db(result['seclabels']) - result.update(frmtd_sec_labels) + # Get Formatted Security Labels + if 'seclabels' in result: + # Security Labels is not available for PostgreSQL <= 9.1 + frmtd_sec_labels = parse_sec_labels_from_db(result['seclabels']) + result.update(frmtd_sec_labels) - # Get Formatted Variables - frmtd_variables = parse_variables_from_db(res1['rows']) - result.update(frmtd_variables) + # Get Formatted Variables + frmtd_variables = parse_variables_from_db(res1['rows']) + result.update(frmtd_variables) sql_header = "-- Database: {0}\n\n-- ".format(result['name']) if hasattr(str, 'decode'): diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py index 036a4cb89..4cafeb2fb 100644 --- a/web/pgadmin/utils/driver/psycopg2/__init__.py +++ b/web/pgadmin/utils/driver/psycopg2/__init__.py @@ -1525,6 +1525,8 @@ WHERE db.oid = {0}""".format(did)) if my_id in self.connections: self.connections[my_id]._release() del self.connections[my_id] + if did is not None: + del self.db_info[did] if len(self.connections) == 0: self.ver = None