Handling the bad/lost connection of a database server.

Made backend changes for:
* Taking care of the connection status in the psycopg2 driver. And, when
  the connection is lost, it throws a exception with 503 http status
  message, and connection lost information in it.
* Allowing the flask application to propagate the exceptions even in the
  release mode.
* Utilising the existing password (while reconnection, if not
  disconnected explicitly).
* Introduced a new ajax response message 'service_unavailable' (http
  status code: 503), which suggests temporary service unavailable.

Client (front-end) changes:
* To handle the connection lost of a database server for different
  operations by generating proper events, and handle them properly.

Removed the connection status check code from different nodes, so that
- it generates the proper exception, when accessing the non-alive
  connection.

Fixes #1387
pull/3/head
Ashesh Vashi 2016-08-29 11:52:50 +05:30
parent 1b05464a04
commit f12d981a9d
51 changed files with 1235 additions and 970 deletions

View File

@ -124,6 +124,7 @@ def create_app(app_name=config.APP_NAME):
# Removes unwanted whitespace from render_template function
app.jinja_env.trim_blocks = True
app.config.from_object(config)
app.config.update(dict(PROPAGATE_EXCEPTIONS=True))
##########################################################################
# Setup session management

View File

@ -85,7 +85,8 @@ class CollectionNodeModule(PgAdminModule, PGChildModule):
"_type": 'coll-%s' % (self.node_type),
"_id": parent_id,
"_pid": parent_id,
"module": 'pgadmin.node.%s' % self.node_type
"module": 'pgadmin.node.%s' % self.node_type,
"subnodes": sorted([m.node_type for m in self.submodules])
}
for key in kwargs:

View File

@ -712,8 +712,16 @@ class ServerNode(PGChildNodeView):
from pgadmin.utils.driver import get_driver
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
conn = manager.connection()
res = conn.connected()
return make_json_response(data={'connected': conn.connected()})
if res:
from pgadmin.utils.exception import ConnectionLost
try:
conn.execute_scalar('SELECT 1')
except ConnectionLost:
res = False
return make_json_response(data={'connected': res})
def connect(self, gid, sid):
"""
@ -752,8 +760,14 @@ class ServerNode(PGChildNodeView):
password = None
save_password = False
# Connect the Server
from pgadmin.utils.driver import get_driver
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
conn = manager.connection()
if 'password' not in data:
if server.password is None:
conn_passwd = getattr(conn, 'password', None)
if conn_passwd is None and server.password is None:
# Return the password template in case password is not
# provided, or password has not been saved earlier.
return make_json_response(
@ -772,19 +786,15 @@ class ServerNode(PGChildNodeView):
data['save_password'] if password and \
'save_password' in data else False
# Encrypt the password before saving with user's login password key.
try:
password = encrypt(password, user.password) \
if password is not None else server.password
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=e.message)
# Connect the Server
from pgadmin.utils.driver import get_driver
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
conn = manager.connection()
# Encrypt the password before saving with user's login password key.
try:
password = encrypt(password, user.password) \
if password is not None else server.password
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=e.message)
status = True
try:
status, errmsg = conn.connect(
password=password,
@ -792,13 +802,18 @@ class ServerNode(PGChildNodeView):
)
except Exception as e:
current_app.logger.exception(e)
# TODO::
# Ask the password again (if existing password couldn't be
# descrypted)
if e.message:
return internal_server_error(errormsg=e.message)
else:
return internal_server_error(errormsg=str(e))
return make_json_response(
success=0,
status=401,
result=render_template(
'servers/password.html',
server_label=server.name,
username=server.username,
errmsg=e.message if e.message else str(e),
_=gettext
)
)
if not status:
current_app.logger.error(

View File

@ -24,7 +24,7 @@ from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error, unauthorized
from pgadmin.utils.ajax import precondition_required, gone
from pgadmin.utils.ajax import gone
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -133,11 +133,6 @@ class DatabaseView(PGChildNodeView):
self.conn = self.manager.connection(did=kwargs['did'])
else:
self.conn = self.manager.connection()
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
_("Connection to the server has been lost!")
)
ver = self.manager.version
# we will set template path for sql scripts
@ -147,6 +142,7 @@ class DatabaseView(PGChildNodeView):
self.template_path = 'databases/sql/9.2_plus'
else:
self.template_path = 'databases/sql/9.1_plus'
return f(self, *args, **kwargs)
return wrapped
@ -156,7 +152,9 @@ class DatabaseView(PGChildNodeView):
@check_precondition(action="list")
def list(self, gid, sid):
last_system_oid = 0 if self.blueprint.show_system_objects else \
(self.manager.db_info[self.manager.did])['datlastsysoid']
(self.manager.db_info[self.manager.did])['datlastsysoid'] \
if self.manager.db_info is not None and \
self.manager.did in self.manager.db_info else 0
SQL = render_template(
"/".join([self.template_path, 'properties.sql']),
conn=self.conn, last_system_oid=last_system_oid
@ -175,8 +173,10 @@ class DatabaseView(PGChildNodeView):
res = []
last_system_oid = 0 if self.blueprint.show_system_objects or \
show_system_templates else (
self.manager.db_info[self.manager.did]
)['datlastsysoid']
(self.manager.db_info[self.manager.did])['datlastsysoid'] \
if self.manager.db_info is not None and \
self.manager.did in self.manager.db_info else 0
)
SQL = render_template(
"/".join([self.template_path, 'nodes.sql']),
@ -403,26 +403,22 @@ class DatabaseView(PGChildNodeView):
This function to return list of avialable encodings
"""
res = [{'label': '', 'value': ''}]
try:
SQL = render_template(
"/".join([self.template_path, 'get_encodings.sql'])
)
status, rset = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
SQL = render_template(
"/".join([self.template_path, 'get_encodings.sql'])
)
status, rset = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=rset)
for row in rset['rows']:
res.append(
{'label': row['encoding'], 'value': row['encoding']}
)
return make_json_response(
data=res,
status=200
for row in rset['rows']:
res.append(
{'label': row['encoding'], 'value': row['encoding']}
)
except Exception as e:
return internal_server_error(errormsg=str(e))
return make_json_response(
data=res,
status=200
)
@check_precondition(action="get_ctypes")
def get_ctypes(self, gid, sid, did=None):
@ -435,25 +431,21 @@ class DatabaseView(PGChildNodeView):
res.append(
{'label': val, 'value': val}
)
try:
SQL = render_template(
"/".join([self.template_path, 'get_ctypes.sql'])
)
status, rset = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
SQL = render_template(
"/".join([self.template_path, 'get_ctypes.sql'])
)
status, rset = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=rset)
for row in rset['rows']:
if row['cname'] not in default_list:
res.append({'label': row['cname'], 'value': row['cname']})
for row in rset['rows']:
if row['cname'] not in default_list:
res.append({'label': row['cname'], 'value': row['cname']})
return make_json_response(
data=res,
status=200
)
except Exception as e:
return internal_server_error(errormsg=str(e))
return make_json_response(
data=res,
status=200
)
@check_precondition(action="create")
def create(self, gid, sid):
@ -475,64 +467,56 @@ class DatabaseView(PGChildNodeView):
"Could not find the required parameter (%s)." % arg
)
)
try:
# The below SQL will execute CREATE DDL only
SQL = render_template(
"/".join([self.template_path, 'create.sql']),
data=data, conn=self.conn
)
# The below SQL will execute CREATE DDL only
SQL = render_template(
"/".join([self.template_path, 'create.sql']),
data=data, conn=self.conn
)
status, msg = self.conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=msg)
if 'datacl' in data:
data['datacl'] = parse_priv_to_db(data['datacl'], 'DATABASE')
# The below SQL will execute rest DMLs because we can not execute CREATE with any other
SQL = render_template(
"/".join([self.template_path, 'grant.sql']),
data=data, conn=self.conn
)
SQL = SQL.strip('\n').strip(' ')
if SQL and SQL != "":
status, msg = self.conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=msg)
if 'datacl' in data:
data['datacl'] = parse_priv_to_db(data['datacl'], 'DATABASE')
# We need oid of newly created database
SQL = render_template(
"/".join([self.template_path, 'properties.sql']),
name=data['name'], conn=self.conn, last_system_oid=0
)
SQL = SQL.strip('\n').strip(' ')
if SQL and SQL != "":
status, res = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
# The below SQL will execute rest DMLs because we can not execute CREATE with any other
SQL = render_template(
"/".join([self.template_path, 'grant.sql']),
data=data, conn=self.conn
)
SQL = SQL.strip('\n').strip(' ')
if SQL and SQL != "":
status, msg = self.conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=msg)
# We need oid of newly created database
SQL = render_template(
"/".join([self.template_path, 'properties.sql']),
name=data['name'], conn=self.conn, last_system_oid=0
)
SQL = SQL.strip('\n').strip(' ')
if SQL and SQL != "":
status, res = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
response = res['rows'][0]
return jsonify(
node=self.blueprint.generate_browser_node(
response['did'],
sid,
response['name'],
icon="icon-database-not-connected",
connected=False,
tablespace=response['default_tablespace'],
allowConn=True,
canCreate=response['cancreate'],
canDisconn=True,
canDrop=True
)
)
except Exception as e:
return make_json_response(
status=410,
success=0,
errormsg=e.message
response = res['rows'][0]
return jsonify(
node=self.blueprint.generate_browser_node(
response['did'],
sid,
response['name'],
icon="icon-database-not-connected",
connected=False,
tablespace=response['default_tablespace'],
allowConn=True,
canCreate=response['cancreate'],
canDisconn=True,
canDrop=True
)
)
@check_precondition(action="update")
def update(self, gid, sid, did):
@ -563,91 +547,79 @@ class DatabaseView(PGChildNodeView):
if 'name' not in data:
data['name'] = data['old_name']
try:
status = self.manager.release(did=did)
conn = self.manager.connection()
for action in ["rename_database", "tablespace"]:
SQL = self.get_offline_sql(gid, sid, data, did, action)
SQL = SQL.strip('\n').strip(' ')
if SQL and SQL != "":
status, msg = conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=msg)
info = "Database updated."
self.conn = self.manager.connection(database=data['name'], auto_reconnect=True)
status, errmsg = self.conn.connect()
SQL = self.get_online_sql(gid, sid, data, did)
status = self.manager.release(did=did)
conn = self.manager.connection()
for action in ["rename_database", "tablespace"]:
SQL = self.get_offline_sql(gid, sid, data, did, action)
SQL = SQL.strip('\n').strip(' ')
if SQL and SQL != "":
status, msg = self.conn.execute_scalar(SQL)
status, msg = conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=msg)
info = "Database updated."
return make_json_response(
success=1,
info=info,
data={
'id': did,
'sid': sid,
'gid': gid,
}
)
self.conn = self.manager.connection(database=data['name'], auto_reconnect=True)
status, errmsg = self.conn.connect()
except Exception as e:
return make_json_response(
status=410,
success=0,
errormsg=str(e)
)
SQL = self.get_online_sql(gid, sid, data, did)
SQL = SQL.strip('\n').strip(' ')
if SQL and SQL != "":
status, msg = self.conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=msg)
info = "Database updated."
return make_json_response(
success=1,
info=info,
data={
'id': did,
'sid': sid,
'gid': gid,
}
)
@check_precondition(action="drop")
def delete(self, gid, sid, did):
"""Delete the database."""
try:
default_conn = self.manager.connection()
SQL = render_template(
"/".join([self.template_path, 'delete.sql']),
did=did, conn=self.conn
)
status, res = default_conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=res)
default_conn = self.manager.connection()
SQL = render_template(
"/".join([self.template_path, 'delete.sql']),
did=did, conn=self.conn
)
status, res = default_conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=res)
if res is None:
return make_json_response(
success=0,
errormsg=_(
'Error: Object not found.'
),
info=_(
'The specified database could not be found.\n'
)
)
else:
status = self.manager.release(did=did)
SQL = render_template(
"/".join([self.template_path, 'delete.sql']),
datname=res, conn=self.conn
)
status, msg = default_conn.execute_scalar(SQL)
if not status:
# reconnect if database drop failed.
conn = self.manager.connection(did=did, auto_reconnect=True)
status, errmsg = conn.connect()
return internal_server_error(errormsg=msg)
except Exception as e:
if res is None:
return make_json_response(
success=0,
errormsg=str(e))
errormsg=_(
'Error: Object not found.'
),
info=_(
'The specified database could not be found.\n'
)
)
else:
status = self.manager.release(did=did)
SQL = render_template(
"/".join([self.template_path, 'delete.sql']),
datname=res, conn=self.conn
)
status, msg = default_conn.execute_scalar(SQL)
if not status:
# reconnect if database drop failed.
conn = self.manager.connection(did=did, auto_reconnect=True)
status, errmsg = conn.connect()
return internal_server_error(errormsg=msg)
return make_json_response(success=1)
@ -662,25 +634,18 @@ class DatabaseView(PGChildNodeView):
data[k] = json.loads(v, encoding='utf-8')
except ValueError:
data[k] = v
try:
status, res = self.get_sql(gid, sid, data, did)
status, res = self.get_sql(gid, sid, data, did)
if not status:
return res
if not status:
return res
res = re.sub('\n{2,}', '\n\n', res)
SQL = res.strip('\n').strip(' ')
res = re.sub('\n{2,}', '\n\n', res)
SQL = res.strip('\n').strip(' ')
return make_json_response(
data=SQL,
status=200
)
except Exception as e:
current_app.logger.exception(e)
return make_json_response(
data=_("-- modified SQL"),
status=200
)
return make_json_response(
data=SQL,
status=200
)
def get_sql(self, gid, sid, data, did=None):
SQL = ''
@ -819,7 +784,10 @@ class DatabaseView(PGChildNodeView):
server.
"""
last_system_oid = 0 if self.blueprint.show_system_objects else \
(self.manager.db_info[self.manager.did])['datlastsysoid']
(self.manager.db_info[self.manager.did])['datlastsysoid'] \
if self.manager.db_info is not None and \
self.manager.did in self.manager.db_info else 0
status, res = self.conn.execute_dict(
render_template(
"/".join([self.template_path, 'stats.sql']),

View File

@ -17,9 +17,8 @@ from flask import render_template, make_response, request, jsonify
from flask_babel import gettext
from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -201,17 +200,8 @@ class CastView(PGChildNodeView):
self = args[0]
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
ver = self.manager.version
# we will set template path for sql scripts
if ver >= 90100:
self.template_path = 'cast/sql/9.1_plus'
# Set template path for the SQL scripts
self.template_path = 'cast/sql/9.1_plus'
return f(*args, **kwargs)
@ -226,9 +216,13 @@ class CastView(PGChildNodeView):
:param did: database id
:return:
"""
last_system_oid = 0 if self.blueprint.show_system_objects else \
(self.manager.db_info[did])['datlastsysoid'] \
if self.manager.db_info is not None and \
did in self.manager.db_info else 0
sql = render_template(
"/".join([self.template_path, 'properties.sql']),
datlastsysoid=self.manager.db_info[did]['datlastsysoid'],
datlastsysoid=last_system_oid,
showsysobj=self.blueprint.show_system_objects
)
status, res = self.conn.execute_dict(sql)
@ -255,9 +249,13 @@ class CastView(PGChildNodeView):
:return:
"""
res = []
last_system_oid = 0 if self.blueprint.show_system_objects else \
(self.manager.db_info[did])['datlastsysoid'] \
if self.manager.db_info is not None and \
did in self.manager.db_info else 0
sql = render_template(
"/".join([self.template_path, 'nodes.sql']),
datlastsysoid=self.manager.db_info[did]['datlastsysoid'],
datlastsysoid=last_system_oid,
showsysobj=self.blueprint.show_system_objects
)
status, rset = self.conn.execute_2darray(sql)
@ -313,17 +311,19 @@ class CastView(PGChildNodeView):
:param cid: cast id
:return:
"""
last_system_oid = (self.manager.db_info[did])['datlastsysoid'] if \
self.manager.db_info is not None and \
did in self.manager.db_info else 0
sql = render_template(
"/".join([self.template_path, 'properties.sql']),
cid=cid,
datlastsysoid=self.manager.db_info[did]['datlastsysoid'],
datlastsysoid=last_system_oid,
showsysobj=self.blueprint.show_system_objects
)
status, res = self.conn.execute_dict(sql)
if not status:
return internal_server_error(errormsg=res)
result = res['rows'][0]
return ajax_response(
response=res['rows'][0],
@ -367,10 +367,14 @@ class CastView(PGChildNodeView):
return internal_server_error(errormsg=res)
# we need oid to to add object in tree at browser, below sql will gives the same
last_system_oid = 0 if self.blueprint.show_system_objects else \
(self.manager.db_info[did])['datlastsysoid'] \
if self.manager.db_info is not None and \
did in self.manager.db_info else 0
sql = render_template("/".join([self.template_path, 'properties.sql']),
srctyp=data['srctyp'],
trgtyp=data['trgtyp'],
datlastsysoid=self.manager.db_info[did]['datlastsysoid'],
datlastsysoid=last_system_oid,
showsysobj=self.blueprint.show_system_objects
)
status, cid = self.conn.execute_scalar(sql)
@ -529,9 +533,13 @@ class CastView(PGChildNodeView):
"""
try:
if cid is not None:
last_system_oid = 0 if self.blueprint.show_system_objects else \
(self.manager.db_info[did])['datlastsysoid'] \
if self.manager.db_info is not none and \
did in self.manager.db_info else 0
sql = render_template("/".join([self.template_path, 'properties.sql']),
cid=cid,
datlastsysoid=self.manager.db_info[did]['datlastsysoid'],
datlastsysoid=last_system_oid,
showsysobj=self.blueprint.show_system_objects)
status, res = self.conn.execute_dict(sql)

View File

@ -16,9 +16,8 @@ from flask import render_template, make_response, request, jsonify
from flask_babel import gettext
from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -188,22 +187,12 @@ class EventTriggerView(PGChildNodeView):
@wraps(f)
def wrap(*args, **kwargs):
# Here args[0] will hold self & kwargs will hold gid,sid,did
# Here - args[0] will always hold self & kwargs will hold gid, sid, did
self = args[0]
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
ver = self.manager.version
if ver >= 90300:
self.template_path = 'event_triggers/sql/9.3_plus'
self.template_path = 'event_triggers/sql/9.3_plus'
return f(*args, **kwargs)

View File

@ -19,9 +19,8 @@ from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -211,17 +210,8 @@ class ForeignDataWrapperView(PGChildNodeView):
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
ver = self.manager.version
# we will set template path for sql scripts
if ver >= 90300:
# Set the template path for the SQL scripts
if self.manager.version >= 90300:
self.template_path = 'foreign_data_wrappers/sql/9.3_plus'
else:
self.template_path = 'foreign_data_wrappers/sql/9.1_plus'

View File

@ -19,9 +19,8 @@ from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -204,18 +203,8 @@ class ForeignServerView(PGChildNodeView):
self = args[0]
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
ver = self.manager.version
# we will set template path for sql scripts
if ver >= 90300:
# Set the template path for the SQL scripts
if self.manager.version >= 90300:
self.template_path = 'foreign_servers/sql/9.3_plus'
else:
self.template_path = 'foreign_servers/sql/9.1_plus'

View File

@ -17,9 +17,8 @@ from flask import render_template, make_response, request, jsonify
from flask_babel import gettext
from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -219,21 +218,9 @@ class UserMappingView(PGChildNodeView):
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
# Set the template path for the SQL scripts
self.template_path = 'user_mappings/sql/9.1_plus'
ver = self.manager.version
# we will set template path for sql scripts
if ver >= 90100:
self.template_path = 'user_mappings/sql/9.1_plus'
return f(*args, **kwargs)
return wrap

View File

@ -19,9 +19,8 @@ from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -229,18 +228,8 @@ class LanguageView(PGChildNodeView):
self.driver = get_driver(PG_DEFAULT_DRIVER)
self.manager = self.driver.connection_manager(kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
ver = self.manager.version
# we will set template path for sql scripts
if ver >= 90300:
# Set the template path for the SQL scripts
if self.manager.version >= 90300:
self.template_path = 'languages/sql/9.3_plus'
else:
self.template_path = 'languages/sql/9.1_plus'

View File

@ -18,10 +18,8 @@ from pgadmin.browser.collection import CollectionNodeModule, PGChildModule
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error, gone, \
bad_request
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone, bad_request
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -129,13 +127,7 @@ def check_precondition(f):
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext("Connection to the server has been lost!")
)
# Set template path for sql scripts
# Set the template path for the SQL scripts
self.template_path = self.template_initial + '/' + (
self.ppas_template_path(self.manager.version)
if self.manager.server_type == 'ppas' else

View File

@ -17,9 +17,8 @@ from flask_babel import gettext
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
import SchemaChildModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -146,14 +145,6 @@ class CatalogObjectView(PGChildNodeView):
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
self.template_path = 'catalog_object/sql/{0}/9.1_plus'.format(
'ppas' if self.manager.server_type == 'ppas' else 'pg'
)

View File

@ -16,9 +16,8 @@ from flask import render_template
from flask_babel import gettext
from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from pgadmin.utils.preferences import Preferences
@ -166,14 +165,6 @@ class CatalogObjectColumnsView(PGChildNodeView):
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
self.template_path = 'catalog_object_column/sql/9.1_plus'
return f(*args, **kwargs)

View File

@ -18,9 +18,8 @@ from flask_babel import gettext
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
import SchemaChildModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -185,18 +184,10 @@ class CollationView(PGChildNodeView):
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
# we will set template path for sql scripts
# Set the template path for the SQL scripts
self.template_path = 'collation/sql/9.1_plus'
return f(*args, **kwargs)
return f(*args, **kwargs)
return wrap
@check_precondition

View File

@ -20,9 +20,8 @@ from pgadmin.browser.server_groups.servers.databases.schemas.utils import \
from pgadmin.browser.server_groups.servers.databases.utils import \
parse_sec_labels_from_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error, gone
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -263,18 +262,10 @@ class DomainView(PGChildNodeView, DataTypeReader):
self.conn = self.manager.connection(did=kwargs['did'])
self.qtIdent = driver.qtIdent
if not self.conn.connected():
return precondition_required(
gettext("Connection to the server has been lost!")
)
ver = self.manager.version
server_type = self.manager.server_type
# we will set template path for sql scripts
if ver >= 90200:
if self.manager.version >= 90200:
self.template_path = 'domains/sql/9.2_plus'
elif ver >= 90100:
else:
self.template_path = 'domains/sql/9.1_plus'
return f(*args, **kwargs)

View File

@ -18,9 +18,8 @@ from flask import render_template, make_response, request, jsonify
from flask_babel import gettext
from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -256,22 +255,13 @@ class DomainConstraintView(PGChildNodeView):
self.conn = self.manager.connection(did=kwargs['did'])
self.qtIdent = driver.qtIdent
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext("Connection to the server has been lost!")
)
ver = self.manager.version
# we will set template path for sql scripts
if ver >= 90200:
# Set the template path for the SQL scripts
if self.manager.version >= 90200:
self.template_path = 'domain_constraints/sql/9.2_plus'
elif ver >= 90100:
else:
self.template_path = 'domain_constraints/sql/9.1_plus'
return f(*args, **kwargs)
return wrap
@check_precondition

View File

@ -25,9 +25,8 @@ from pgadmin.browser.server_groups.servers.databases.utils import \
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error, gone
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -338,16 +337,8 @@ class ForeignTableView(PGChildNodeView, DataTypeReader):
# Get database connection
self.conn = self.manager.connection(did=kwargs['did'])
self.qtIdent = driver.qtIdent
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
ver = self.manager.version
# Set template path for sql scripts depending
# on the server version.
@ -360,7 +351,6 @@ class ForeignTableView(PGChildNodeView, DataTypeReader):
self.template_path = 'foreign_tables/sql/9.1_plus'
return f(*args, **kwargs)
return wrap
@check_precondition

View File

@ -18,9 +18,8 @@ from flask_babel import gettext as _
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
import SchemaChildModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error, gone
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -230,17 +229,10 @@ class FtsConfigurationView(PGChildNodeView):
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
_("Connection to the server has been lost!")
)
# we will set template path for sql scripts depending upon server version
ver = self.manager.version
if ver >= 90100:
self.template_path = 'fts_configuration/sql/9.1_plus'
return f(*args, **kwargs)
# Set the template path for the SQL scripts
self.template_path = 'fts_configuration/sql/9.1_plus'
return f(*args, **kwargs)
return wrap
@check_precondition
@ -741,7 +733,6 @@ class FtsConfigurationView(PGChildNodeView):
:param scid: schema id
"""
# Fetch last system oid
datlastsysoid = self.manager.db_info[did]['datlastsysoid']
sql = render_template(
"/".join([self.template_path, 'parser.sql']),
@ -752,6 +743,8 @@ class FtsConfigurationView(PGChildNodeView):
if not status:
return internal_server_error(errormsg=rset)
datlastsysoid = self.manager.db_info[did]['datlastsysoid']
# Empty set is added before actual list as initially it will be visible
# at parser control while creating a new FTS Configuration
res = [{'label': '', 'value': ''}]
@ -776,8 +769,6 @@ class FtsConfigurationView(PGChildNodeView):
:param scid: schema id
"""
# Fetch last system oid
datlastsysoid = self.manager.db_info[did]['datlastsysoid']
sql = render_template(
"/".join([self.template_path, 'copy_config.sql']),
copy_config=True
@ -787,6 +778,8 @@ class FtsConfigurationView(PGChildNodeView):
if not status:
return internal_server_error(errormsg=rset)
datlastsysoid = self.manager.db_info[did]['datlastsysoid']
# Empty set is added before actual list as initially it will be visible
# at copy_config control while creating a new FTS Configuration
res = [{'label': '', 'value': ''}]

View File

@ -18,9 +18,8 @@ from flask_babel import gettext as _
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
import SchemaChildModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error, gone
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -222,17 +221,10 @@ class FtsDictionaryView(PGChildNodeView):
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
_("Connection to the server has been lost!")
)
# we will set template path for sql scripts depending upon server version
ver = self.manager.version
if ver >= 90100:
self.template_path = 'fts_dictionary/sql/9.1_plus'
return f(*args, **kwargs)
# Set the template path for the SQL scripts
self.template_path = 'fts_dictionary/sql/9.1_plus'
return f(*args, **kwargs)
return wrap
def tokenize_options(self, option_value):
@ -725,8 +717,6 @@ class FtsDictionaryView(PGChildNodeView):
:param scid: schema id
"""
# Fetch last system oid
datlastsysoid = self.manager.db_info[did]['datlastsysoid']
sql = render_template("/".join([self.template_path, 'templates.sql']),
template=True)
status, rset = self.conn.execute_dict(sql)
@ -734,6 +724,7 @@ class FtsDictionaryView(PGChildNodeView):
if not status:
return internal_server_error(errormsg=rset)
datlastsysoid = self.manager.db_info[did]['datlastsysoid']
# Empty set is added before actual list as initially it will be visible
# at template control while creating a new FTS Dictionary
res = [{'label': '', 'value': ''}]

View File

@ -17,9 +17,8 @@ from flask_babel import gettext as _
from pgadmin.browser.server_groups.servers.databases import DatabaseModule
from pgadmin.browser.server_groups.servers.databases.schemas.utils import SchemaChildModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -220,19 +219,10 @@ class FtsParserView(PGChildNodeView):
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
_(
"Connection to the server has been lost!"
)
)
# we will set template path for sql scripts depending upon server version
ver = self.manager.version
if ver >= 90100:
self.template_path = 'fts_parser/sql/9.1_plus'
return f(*args, **kwargs)
# Set the template path for the SQL scripts
self.template_path = 'fts_parser/sql/9.1_plus'
return f(*args, **kwargs)
return wrap
@check_precondition

View File

@ -17,9 +17,8 @@ from flask_babel import gettext
from pgadmin.browser.server_groups.servers.databases import DatabaseModule
from pgadmin.browser.server_groups.servers.databases.schemas.utils import SchemaChildModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -209,19 +208,9 @@ class FtsTemplateView(PGChildNodeView):
self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
# we will set template path for sql scripts depending upon server version
ver = self.manager.version
if ver >= 90100:
self.template_path = 'fts_template/sql/9.1_plus'
return f(*args, **kwargs)
self.template_path = 'fts_template/sql/9.1_plus'
return f(*args, **kwargs)
return wrap
@check_precondition
@ -267,7 +256,6 @@ class FtsTemplateView(PGChildNodeView):
@check_precondition
def node(self, gid, sid, did, scid, tid):
res = []
sql = render_template(
"/".join([self.template_path, 'nodes.sql']),
tid=tid
@ -286,6 +274,9 @@ class FtsTemplateView(PGChildNodeView):
),
status=200
)
return gone(
_("Could not the requested FTS template.")
)
@check_precondition
def properties(self, gid, sid, did, scid, tid):
@ -609,9 +600,9 @@ class FtsTemplateView(PGChildNodeView):
:param scid: schema id
:param tid: fts tempate id
"""
data = request.args
sql = render_template("/".join([self.template_path, 'functions.sql']),
lexize=True)
sql = render_template(
"/".join([self.template_path, 'functions.sql']), lexize=True
)
status, rset = self.conn.execute_dict(sql)
if not status:
@ -638,9 +629,9 @@ class FtsTemplateView(PGChildNodeView):
:param scid: schema id
:param tid: fts tempate id
"""
data = request.args
sql = render_template("/".join([self.template_path, 'functions.sql']),
init=True)
sql = render_template(
"/".join([self.template_path, 'functions.sql']), init=True
)
status, rset = self.conn.execute_dict(sql)
if not status:

View File

@ -27,9 +27,8 @@ from pgadmin.browser.server_groups.servers.databases.utils import \
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error, gone
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, gone
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -329,21 +328,12 @@ class FunctionView(PGChildNodeView, DataTypeReader):
# Get database connection
self.conn = self.manager.connection(did=kwargs['did'])
self.qtIdent = driver.qtIdent
self.qtLiteral = driver.qtLiteral
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
ver = self.manager.version
# Set template path for sql scripts depending
# on the server version.
# Set the template path for the SQL scripts
self.template_path = "/".join([
self.node_type
])
@ -469,10 +459,9 @@ class FunctionView(PGChildNodeView, DataTypeReader):
proallargtypes = data['proallargtypes'] \
if data['proallargtypes'] else []
proargout = []
proargid = []
proargmodenames = {'i': 'IN', 'o': 'OUT', 'b': 'INOUT',
'v': 'VARIADIC', 't': 'TABLE'}
proargmodenames = {
'i': 'IN', 'o': 'OUT', 'b': 'INOUT', 'v': 'VARIADIC', 't': 'TABLE'
}
# The proargtypes doesn't give OUT params, so we need to fetch
# those from database explicitly, below code is written for this
@ -1325,7 +1314,6 @@ It may have been removed by another user or moved to another schema.
if not status:
return internal_server_error(errormsg=res)
func_def = res['rows'][0]['func_def']
name = res['rows'][0]['name']
# Fetch only arguments

View File

@ -20,9 +20,8 @@ from pgadmin.browser.server_groups.servers.databases.schemas.utils \
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -145,20 +144,11 @@ class SequenceView(PGChildNodeView):
self.conn = self.manager.connection(did=kwargs['did'])
else:
self.conn = self.manager.connection()
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
_(
"Connection to the server has been lost!"
)
)
self.template_path = 'sequence/sql/9.1_plus'
self.acl = ['r', 'w', 'U']
return f(self, *args, **kwargs)
return wrapped
return wrap
@check_precondition(action='list')
@ -336,10 +326,10 @@ class SequenceView(PGChildNodeView):
# We need oid of newly created sequence.
SQL = render_template("/".join([self.template_path, 'get_oid.sql']), name=data['name'], scid=scid)
SQL = SQL.strip('\n').strip(' ')
if SQL and SQL != "":
status, seid = self.conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=res)
status, seid = self.conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=seid)
return jsonify(
node=self.blueprint.generate_browser_node(
@ -504,18 +494,13 @@ class SequenceView(PGChildNodeView):
"Could not find the required parameter (%s)." % arg
)
)
try:
SQL = self.getSQL(gid, sid, did, data, scid, seid)
SQL = SQL.strip('\n').strip(' ')
return make_json_response(
data=SQL,
status=200
)
except Exception as e:
return make_json_response(
data="-- modified SQL",
status=200
)
SQL = self.getSQL(gid, sid, did, data, scid, seid)
SQL = SQL.strip('\n').strip(' ')
return make_json_response(
data=SQL,
status=200
)
def getSQL(self, gid, sid, did, data, scid, seid=None):
"""

View File

@ -22,9 +22,8 @@ from pgadmin.browser.server_groups.servers.databases.schemas.utils \
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -272,22 +271,18 @@ class TableView(PGChildNodeView, DataTypeReader, VacuumSettings):
# Here args[0] will hold self & kwargs will hold gid,sid,did
self = args[0]
driver = get_driver(PG_DEFAULT_DRIVER)
did = kwargs['did']
self.manager = driver.connection_manager(kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
self.qtIdent = driver.qtIdent
# We need datlastsysoid to check if current table is system table
self.datlastsysoid = self.manager.db_info[kwargs['did']]['datlastsysoid']
self.server_type = self.manager.server_type
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
# we will set template path for sql scripts
self.datlastsysoid = self.manager.db_info[
did
]['datlastsysoid'] if self.manager.db_info is not None and \
did in self.manager.db_info else 0
ver = self.manager.version
# Template for Column node
# Set the template path for the SQL scripts
if ver >= 90500:
self.template_path = 'table/sql/9.5_plus'
else:
@ -1193,7 +1188,7 @@ class TableView(PGChildNodeView, DataTypeReader, VacuumSettings):
try:
SQL = render_template("/".join([self.template_path,
'get_oftype.sql']), scid=scid,
server_type=self.server_type,
server_type=self.manager.server_type,
show_sys_objects=self.blueprint.show_system_objects)
status, rset = self.conn.execute_2darray(SQL)
if not status:
@ -1224,7 +1219,7 @@ class TableView(PGChildNodeView, DataTypeReader, VacuumSettings):
SQL = render_template("/".join([self.template_path, 'get_inherits.sql']),
show_system_objects=self.blueprint.show_system_objects,
tid=tid,
server_type=self.server_type)
server_type=self.manager.server_type)
status, rset = self.conn.execute_2darray(SQL)
if not status:
return internal_server_error(errormsg=res)
@ -1253,7 +1248,7 @@ class TableView(PGChildNodeView, DataTypeReader, VacuumSettings):
try:
SQL = render_template("/".join([self.template_path, 'get_relations.sql']),
show_sys_objects=self.blueprint.show_system_objects,
server_type=self.server_type)
server_type=self.manager.server_type)
status, rset = self.conn.execute_2darray(SQL)
if not status:
return internal_server_error(errormsg=res)

View File

@ -21,9 +21,8 @@ from pgadmin.browser.server_groups.servers.databases.schemas.utils \
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -199,17 +198,9 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
)
self.conn = self.manager.connection(did=kwargs['did'])
self.qtIdent = driver.qtIdent
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
ver = self.manager.version
# we will set template path for sql scripts
if ver >= 90200:
# Set the template path for the SQL scripts
if self.manager.version >= 90200:
self.template_path = 'column/sql/9.2_plus'
else:
self.template_path = 'column/sql/9.1_plus'

View File

@ -19,9 +19,8 @@ from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.server_groups.servers.databases.schemas.tables.constraints.type \
import ConstraintRegistry
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -208,15 +207,8 @@ class CheckConstraintView(PGChildNodeView):
self.conn = self.manager.connection(did=kwargs['did'])
self.qtIdent = driver.qtIdent
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
_("Connection to the server has been lost!")
)
ver = self.manager.version
# we will set template path for sql scripts
# Set the template path for the SQL scripts
if ver >= 90200:
self.template_path = 'check_constraint/sql/9.2_plus'
elif ver >= 90100:

View File

@ -18,9 +18,8 @@ from flask_babel import gettext as _
from pgadmin.browser.server_groups.servers.databases.schemas.tables.constraints.type \
import ConstraintRegistry, ConstraintTypeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -216,16 +215,7 @@ class ExclusionConstraintView(PGChildNodeView):
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
_(
"Connection to the server has been lost!"
)
)
ver = self.manager.version
if ver >= 90200:
self.template_path = 'exclusion_constraint/sql/9.2_plus'
elif ver >= 90100:
@ -242,8 +232,8 @@ class ExclusionConstraintView(PGChildNodeView):
for row in rset['rows']:
self.schema = row['schema']
self.table = row['table']
return f(*args, **kwargs)
return f(*args, **kwargs)
return wrap
def end_transaction(self):

View File

@ -18,9 +18,8 @@ from flask_babel import gettext as _
from pgadmin.browser.server_groups.servers.databases.schemas.tables.constraints.type \
import ConstraintRegistry, ConstraintTypeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -194,7 +193,7 @@ class ForeignKeyConstraintView(PGChildNodeView):
],
'delete': [{'delete': 'delete'}],
'children': [{'get': 'children'}],
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
'nodes': [{'get': 'nodes'}, {'get': 'nodes'}],
'sql': [{'get': 'sql'}],
'msql': [{'get': 'msql'}, {'get': 'msql'}],
'stats': [{'get': 'statistics'}],
@ -234,16 +233,8 @@ class ForeignKeyConstraintView(PGChildNodeView):
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
_(
"Connection to the server has been lost!"
)
)
self.template_path = 'foreign_key/sql'
# We need parent's name eg table name and schema name
SQL = render_template("/".join([self.template_path,
'get_parent.sql']),
@ -255,8 +246,8 @@ class ForeignKeyConstraintView(PGChildNodeView):
for row in rset['rows']:
self.schema = row['schema']
self.table = row['table']
return f(*args, **kwargs)
return f(*args, **kwargs)
return wrap
def end_transaction(self):
@ -398,31 +389,8 @@ class ForeignKeyConstraintView(PGChildNodeView):
Returns:
"""
try:
res = self.get_nodes(gid, sid, did, scid, tid, fkid)
return make_json_response(
data=res,
status=200
)
except Exception as e:
return internal_server_error(errormsg=str(e))
res = self.get_nodes(gid, sid, did, scid, tid, fkid)
@check_precondition
def get_nodes(self, gid, sid, did, scid, tid, fkid=None):
"""
This function returns all event trigger nodes as a list.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
tid: Table ID
fkid: Foreign key constraint ID
Returns:
"""
res = []
SQL = render_template("/".join([self.template_path,
'nodes.sql']),
@ -444,7 +412,11 @@ class ForeignKeyConstraintView(PGChildNodeView):
icon=icon,
valid=valid
))
return res
return make_json_response(
data=res,
status=200
)
@check_precondition
def create(self, gid, sid, did, scid, tid, fkid=None):

View File

@ -18,9 +18,8 @@ from flask_babel import gettext as _
from pgadmin.browser.server_groups.servers.databases.schemas.tables.constraints.type \
import ConstraintRegistry, ConstraintTypeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -237,16 +236,8 @@ class IndexConstraintView(PGChildNodeView):
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
_(
"Connection to the server has been lost!"
)
)
self.template_path = 'index_constraint/sql'
# We need parent's name eg table name and schema name
SQL = render_template("/".join([self.template_path,
'get_parent.sql']),

View File

@ -1,7 +1,7 @@
define(
[
'jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser',
'pgadmin.browser.collection'{% for c in constraints %}, 'pgadmin.node.{{ c|safe }}'{%endfor%}
'pgadmin.browser.collection'{% for c in constraints %}, 'pgadmin.node.{{ c }}'{%endfor%}
],
function($, _, S, pgAdmin, pgBrowser) {
@ -51,4 +51,4 @@ function($, _, S, pgAdmin, pgBrowser) {
}
return pgBrowser.Nodes['constraints'];
});
});

View File

@ -17,9 +17,8 @@ from flask import render_template, request, jsonify
from flask_babel import gettext
from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -69,13 +68,6 @@ class IndexesModule(CollectionNodeModule):
"""
if super(IndexesModule, self).BackendSupported(manager, **kwargs):
conn = manager.connection(did=kwargs['did'])
# If DB is not connected then return error to browser
if not conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
if 'vid' not in kwargs:
return True
@ -228,16 +220,11 @@ class IndexesView(PGChildNodeView):
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
# We need datlastsysoid to check if current index is system index
self.datlastsysoid = self.manager.db_info[kwargs['did']]['datlastsysoid']
self.datlastsysoid = self.manager.db_info[
kwargs['did']
]['datlastsysoid'] if self.manager.db_info is not None and \
kwargs['did'] in self.manager.db_info else 0
# we will set template path for sql scripts
self.template_path = 'index/sql/9.1_plus'
@ -440,7 +427,6 @@ class IndexesView(PGChildNodeView):
# 'options' we need true/false to render switch ASC(false)/DESC(true)
columns = []
cols = []
cnt = 1
for row in rset['rows']:
# We need all data as collection for ColumnsModel
cols_data = {

View File

@ -19,9 +19,8 @@ from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.server_groups.servers.databases.schemas.utils import \
parse_rule_definition
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -53,13 +52,6 @@ class RuleModule(CollectionNodeModule):
"""
if super(RuleModule, self).BackendSupported(manager, **kwargs):
conn = manager.connection(did=kwargs['did'])
# If DB is not connected then return error to browser
if not conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
if 'vid' not in kwargs:
return True
@ -202,16 +194,10 @@ class RuleView(PGChildNodeView):
self.manager = get_driver(
PG_DEFAULT_DRIVER).connection_manager(kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
self.datlastsysoid = self.manager.db_info[kwargs['did']]['datlastsysoid']
self.datlastsysoid = self.manager.db_info[
kwargs['did']
]['datlastsysoid'] if self.manager.db_info is not None and \
kwargs['did'] in self.manager.db_info else 0
self.template_path = 'rules/sql'
return f(*args, **kwargs)

View File

@ -4,4 +4,4 @@ SELECT ct.oid,
FROM pg_constraint ct
WHERE contype='f' AND
conrelid = {{tid}}::oid
ORDER BY conname
ORDER BY conname

View File

@ -17,9 +17,8 @@ from flask import render_template, request, jsonify
from flask_babel import gettext
from pgadmin.browser.collection import CollectionNodeModule
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -69,24 +68,21 @@ class TriggerModule(CollectionNodeModule):
"""
if super(TriggerModule, self).BackendSupported(manager, **kwargs):
conn = manager.connection(did=kwargs['did'])
# If DB is not connected then return error to browser
if not conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
if 'vid' not in kwargs:
return True
template_path = 'trigger/sql/9.1_plus'
SQL = render_template("/".join(
[template_path, 'backend_support.sql']), vid=kwargs['vid'])
[template_path, 'backend_support.sql']), vid=kwargs['vid']
)
status, res = conn.execute_scalar(SQL)
# check if any errors
if not status:
return internal_server_error(errormsg=res)
# Check vid is view not material view
# then true, othewise false
return res
@ -255,16 +251,11 @@ class TriggerView(PGChildNodeView):
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
# We need datlastsysoid to check if current trigger is system trigger
self.datlastsysoid = self.manager.db_info[kwargs['did']]['datlastsysoid']
self.datlastsysoid = self.manager.db_info[
kwargs['did']
]['datlastsysoid'] if self.manager.db_info is not None and \
kwargs['did'] in self.manager.db_info else 0
# we will set template path for sql scripts
self.template_path = 'trigger/sql/9.1_plus'

View File

@ -20,9 +20,8 @@ from pgadmin.browser.server_groups.servers.databases.schemas.utils \
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
parse_priv_to_db
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -223,15 +222,10 @@ class TypeView(PGChildNodeView, DataTypeReader):
self.conn = self.manager.connection(did=kwargs['did'])
# We need datlastsysoid to check if current type is system type
self.datlastsysoid = self.manager.db_info[kwargs['did']]['datlastsysoid']
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost!"
)
)
self.datlastsysoid = self.manager.db_info[
kwargs['did']
]['datlastsysoid'] if self.manager.db_info is not None and \
kwargs['did'] in self.manager.db_info else 0
# Declare allows acl on type
self.acl = ['U']
@ -240,7 +234,6 @@ class TypeView(PGChildNodeView, DataTypeReader):
self.template_path = 'type/sql/9.1_plus'
return f(*args, **kwargs)
return wrap
@check_precondition

View File

@ -18,10 +18,8 @@ from flask_babel import gettext
from pgadmin.browser.server_groups.servers.databases.schemas.utils import \
SchemaChildModule, parse_rule_definition, VacuumSettings
from pgadmin.browser.utils import PGChildNodeView
from pgadmin.utils.ajax import make_json_response, \
make_response as ajax_response, internal_server_error, \
bad_request
from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
make_response as ajax_response, bad_request
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
@ -171,13 +169,10 @@ def check_precondition(f):
kwargs['sid']
)
self.conn = self.manager.connection(did=kwargs['did'])
# If DB not connected then return error to browser
if not self.conn.connected():
return precondition_required(
gettext("Connection to the server has been lost!")
)
self.datlastsysoid = self.manager.db_info[
kwargs['did']]['datlastsysoid']
kwargs['did']
]['datlastsysoid'] if self.manager.db_info is not None and \
kwargs['did'] in self.manager.db_info else 0
# Set template path for sql scripts
self.template_path = self.template_initial + '/' + (

View File

@ -69,6 +69,11 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
category: 'drop', priority: 5, label: '{{ _('Disconnect Database...') }}',
icon: 'fa fa-chain-broken', enable : 'is_connected'
}]);
_.bindAll(this, 'connection_lost');
pgBrowser.Events.on(
'pgadmin:database:connection:lost', this.connection_lost
);
},
can_create_database: function(node, item) {
var treeData = this.getTreeNodeHierarchy(item),
@ -82,6 +87,67 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
is_connected: function(node) {
return (node && node.connected == true && node.canDisconn == true);
},
connection_lost: function(i, resp, server_connected) {
if (pgBrowser.tree) {
var t = pgBrowser.tree,
info = i && this.getTreeNodeHierarchy(i),
s = null,
d = i && t.itemData(i),
self = this,
_i = i;
while (d && d._type != 'database') {
i = t.parent(i);
d = i && t.itemData(i);
}
if (i && d) {
if (_.isUndefined(d.is_connecting) || !d.is_connecting) {
d.is_connecting = true;
var disconnect = function(_i, _d) {
if (_d._id == this._id) {
d.is_connecting = false;
pgBrowser.Events.off(
'pgadmin:database:connect:cancelled', disconnect
);
_i = _i && t.parent(_i);
_d = _i && t.itemData(_i);
if (_i && _d) {
pgBrowser.Events.trigger(
'pgadmin:server:disconnect',
{item: _i, data: _d}, false
);
}
}
};
pgBrowser.Events.on(
'pgadmin:database:connect:cancelled', disconnect
);
if (server_connected) {
connect(self, d, t, i, true);
return;
}
Alertify.confirm(
'{{ _('Connection lost') }}',
'{{ _('Would you like to reconnect to the database?') }}',
function() {
connect(self, d, t, i, true);
},
function() {
d.is_connecting = false;
t.unload(i);
t.setInode(i);
t.addIcon(i, {icon: 'icon-database-not-connected'});
pgBrowser.Events.trigger(
'pgadmin:database:connect:cancelled', i, d, self
);
});
}
}
}
},
callbacks: {
/* Connect the database */
connect_database: function(args){
@ -374,58 +440,91 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
return null;
}
})
});
function connect_to_database(obj, data, tree, item, interactive) {
connect(obj, data, tree, item)
};
function connect(obj, data, tree, item) {
var onFailure = function(xhr, status, error, _model, _data, _tree, _item) {
});
tree.setInode(_item);
tree.addIcon(_item, {icon: 'icon-database-not-connected'});
function connect_to_database(obj, data, tree, item, interactive) {
connect(obj, data, tree, item)
}
Alertify.pgNotifier('error', xhr, error, function(msg) {
setTimeout(function() {
Alertify.dlgServerPass(
'{{ _('Connect to database') }}',
msg, _model, _data, _tree, _item
).resizeTo();
}, 100);
});
},
onSuccess = function(res, model, data, tree, item) {
tree.deselect(item);
tree.setInode(item);
if (res && res.data) {
if(typeof res.data.connected == 'boolean') {
data.connected = res.data.connected;
}
if (typeof res.data.icon == 'string') {
tree.removeIcon(item);
data.icon = res.data.icon;
tree.addIcon(item, {icon: data.icon});
}
Alertify.success(res.info);
setTimeout(function() {tree.select(item);}, 10);
setTimeout(function() {tree.open(item);}, 100);
}
},
url = obj.generate_url(item, "connect", data, true);
$.post(url)
.done(
function(res) {
if (res.success == 1) {
return onSuccess(res, obj, data, tree, item);
function connect(obj, data, tree, item, _wasConnected) {
var wasConnected = _wasConnected || data.connected,
onFailure = function(
xhr, status, error, _model, _data, _tree, _item, _status
) {
if (!_status) {
tree.setInode(_item);
tree.addIcon(_item, {icon: 'icon-database-not-connected'});
}
})
.fail(
function(xhr, status, error) {
return onFailure(xhr, status, error, obj, data, tree, item);
});
}
Alertify.pgNotifier('error', xhr, error, function(msg) {
setTimeout(function() {
Alertify.dlgServerPass(
'{{ _('Connect to database') }}',
msg, _model, _data, _tree, _item, _status,
onSuccess, onFailure, onCancel
).resizeTo();
}, 100);
});
},
onSuccess = function(
res, model, data, tree, item, connected
) {
data.is_connecting = false;
if (!connected) {
tree.deselect(item);
tree.setInode(item);
}
if (res && res.data) {
if(typeof res.data.connected == 'boolean') {
data.connected = res.data.connected;
}
if (typeof res.data.icon == 'string') {
tree.removeIcon(item);
data.icon = res.data.icon;
tree.addIcon(item, {icon: data.icon});
}
Alertify.success(res.info);
obj.trigger('connected', obj, item, data);
pgBrowser.Events.trigger(
'pgadmin:database:connected', item, data
);
if (!connected) {
setTimeout(function() {
tree.select(item);
tree.open(item);
}, 10);
}
}
},
onCancel = function(_tree, _item, _data, _status) {
_data.is_connecting = false;
var server = _tree.parent(_item);
_tree.unload(_item);
_tree.setInode(_item);
_tree.removeIcon(_item);
_tree.addIcon(_item, {icon: 'icon-database-not-connected'});
obj.trigger('connect:cancelled', obj, _item, _data);
pgBrowser.Events.trigger(
'pgadmin:database:connect:cancelled', _item, _data, obj
);
_tree.select(server);
};
$.post(
obj.generate_url(item, "connect", data, true)
).done(function(res) {
if (res.success == 1) {
return onSuccess(res, obj, data, tree, item, wasConnected);
}
}).fail(function(xhr, status, error) {
return onFailure(
xhr, status, error, obj, data, tree, item, wasConnected
);
});
}
}
return pgBrowser.Nodes['coll-database'];

View File

@ -102,6 +102,18 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
'{{ _('A grantee must be selected.') }}';
pgBrowser.messages['NO_PRIV_SELECTED'] =
'{{ _('At least one privilege should be selected.') }}';
pgBrowser.Events.on(
'pgadmin:server:disconnect', this.callbacks.disconnect_server
);
pgBrowser.Events.on(
'pgadmin:server:connect', this.callbacks.connect_server
);
_.bindAll(this, 'connection_lost');
pgBrowser.Events.on(
'pgadmin:server:connection:lost', this.connection_lost
);
},
is_not_connected: function(node) {
return (node && node.connected != true);
@ -158,11 +170,11 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!d)
return false;
connect_to_server(obj, d, t, i);
connect_to_server(obj, d, t, i, false);
return false;
},
/* Disconnect the server */
disconnect_server: function(args) {
disconnect_server: function(args, notify) {
var input = args || {},
obj = this,
t = pgBrowser.tree,
@ -172,48 +184,60 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!d)
return false;
alertify.confirm(
'{{ _('Disconnect server') }}',
S('{{ _('Are you sure you want to disconnect the server %s?') }}').sprintf(d.label).value(),
function(evt) {
$.ajax({
url: obj.generate_url(i, 'connect', d, true),
type:'DELETE',
success: function(res) {
if (res.success == 1) {
alertify.success(res.info);
d = t.itemData(i);
t.removeIcon(i);
d.connected = false;
d.icon = 'icon-server-not-connected';
t.addIcon(i, {icon: d.icon});
obj.callbacks.refresh.apply(obj, [null, i]);
if (pgBrowser.serverInfo && d._id in pgBrowser.serverInfo) {
delete pgBrowser.serverInfo[d._id]
}
obj.trigger('server-disconnected', obj, i, d);
notify = notify || _.isUndefined(notify) || _.isNull(notify);
var disconnect = function() {
$.ajax({
url: obj.generate_url(i, 'connect', d, true),
type:'DELETE',
success: function(res) {
if (res.success == 1) {
alertify.success(res.info);
d = t.itemData(i);
t.removeIcon(i);
d.connected = false;
d.icon = 'icon-server-not-connected';
t.addIcon(i, {icon: d.icon});
obj.callbacks.refresh.apply(obj, [null, i]);
if (pgBrowser.serverInfo && d._id in pgBrowser.serverInfo) {
delete pgBrowser.serverInfo[d._id]
}
else {
try {
alertify.error(res.errormsg);
} catch (e) {}
t.unload(i);
}
},
error: function(xhr, status, error) {
obj.trigger('server-disconnected', obj, i, d);
}
else {
try {
var err = $.parseJSON(xhr.responseText);
if (err.success == 0) {
alertify.error(err.errormsg);
}
alertify.error(res.errormsg);
} catch (e) {}
t.unload(i);
}
},
error: function(xhr, status, error) {
try {
var err = $.parseJSON(xhr.responseText);
if (err.success == 0) {
alertify.error(err.errormsg);
}
} catch (e) {}
t.unload(i);
}
});
};
if (notify) {
alertify.confirm(
'{{ _('Disconnect server') }}',
S('{{ _('Are you sure you want to disconnect the server %s?') }}').sprintf(
d.label
).value(),
function(evt) {
disconnect();
},
function(evt) {
return true;
});
},
function(evt) {
return true;
});
} else {
disconnect();
}
return false;
},
@ -226,7 +250,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
pgBrowser.tree.addIcon(item, {icon: data.icon});
if (!data.connected) {
connect_to_server(this, data, pgBrowser.tree, item);
connect_to_server(this, data, pgBrowser.tree, item, false);
return false;
}
@ -409,7 +433,6 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
}
},
prepare: function() {
//console.log(this.get('server').user.name);
var self = this;
// Disable Backup button until user provides Filename
this.__internal.buttons[0].element.disabled = true;
@ -487,13 +510,14 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
alertify.changeServerPassword(d).resizeTo('40%','52%');
return false;
},
/* Pause WAL Replay */
pause_wal_replay: function(args) {
var input = args || {};
obj = this,
t = pgBrowser.tree,
i = input.item || t.selected(),
d = i && i.length == 1 ? t.itemData(i) : undefined;
var input = args || {},
obj = this,
t = pgBrowser.tree,
i = input.item || t.selected(),
d = i && i.length == 1 ? t.itemData(i) : undefined;
if (!d)
return false;
@ -528,13 +552,14 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
}
})
},
/* Resume WAL Replay */
resume_wal_replay: function(args) {
var input = args || {};
obj = this,
t = pgBrowser.tree,
i = input.item || t.selected(),
d = i && i.length == 1 ? t.itemData(i) : undefined;
var input = args || {},
obj = this,
t = pgBrowser.tree,
i = input.item || t.selected(),
d = i && i.length == 1 ? t.itemData(i) : undefined;
if (!d)
return false;
@ -709,66 +734,157 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
isConnected: function(model) {
return model.get('connected');
}
})
});
function connect_to_server(obj, data, tree, item) {
var onFailure = function(xhr, status, error, _model, _data, _tree, _item) {
}),
connection_lost: function(i, resp) {
if (pgBrowser.tree) {
var t = pgBrowser.tree,
info = i && this.getTreeNodeHierarchy(i),
s = null,
d = i && t.itemData(i),
self = this;
tree.setInode(_item);
tree.addIcon(_item, {icon: 'icon-server-not-connected'});
alertify.pgNotifier('error', xhr, error, function(msg) {
setTimeout(function() {
alertify.dlgServerPass(
'{{ _('Connect to Server') }}',
msg, _model, _data, _tree, _item
).resizeTo();
}, 100);
});
},
onSuccess = function(res, model, data, tree, item) {
tree.deselect(item);
tree.setInode(item);
if (res && res.data) {
if (typeof res.data.icon == 'string') {
tree.removeIcon(item);
data.icon = res.data.icon;
tree.addIcon(item, {icon: data.icon});
while (d && d._type != 'server') {
i = t.parent(i);
d = i && t.itemData(i);
}
// Update 'in_recovery' and 'wal_pause' options at server node
tree.itemData(item).in_recovery=res.data.in_recovery;
tree.itemData(item).wal_pause=res.data.wal_pause;
if (i && d && d._type == 'server') {
if (_.isUndefined(d.is_connecting) || !d.is_connecting) {
d.is_connecting = true;
_.extend(data, res.data);
var disconnect = function(_sid) {
if (d._id == _sid) {
d.is_connecting = false;
// Stop listening to the connection cancellation event
pgBrowser.Events.off(
'pgadmin:server:connect:cancelled', disconnect
);
var serverInfo = pgBrowser.serverInfo = pgBrowser.serverInfo || {};
serverInfo[data._id] = _.extend({}, data);
// Connection to the database will also be cancelled
pgBrowser.Events.trigger(
'pgadmin:database:connect:cancelled',_sid,
resp.data.database || d.db
);
alertify.success(res.info);
obj.trigger('server-connected', obj, item, data);
setTimeout(function() {
tree.select(item);
tree.open(item);
}, 10);
// Make sure - the server is disconnected properly
pgBrowser.Events.trigger(
'pgadmin:server:disconnect',
{item: _i, data: _d}, false
);
}
};
// Listen for the server connection cancellation event
pgBrowser.Events.on(
'pgadmin:server:connect:cancelled', disconnect
);
alertify.confirm(
'{{ _('Connection lost') }}',
'{{ _('Would you like to reconnect to the database?') }}',
function() {
connect_to_server(self, d, t, i, true);
},
function() {
d.is_connecting = false;
t.unload(i);
t.setInode(i);
t.addIcon(i, {icon: 'icon-database-not-connected'});
pgBrowser.Events.trigger(
'pgadmin:server:connect:cancelled', i, d, self
);
t.select(i);
});
}
}
}
};
}
});
function connect_to_server(obj, data, tree, item, reconnect) {
var wasConnected = reconnect || data.connected,
onFailure = function(
xhr, status, error, _node, _data, _tree, _item, _wasConnected
) {
data.connected = false;
// It should be attempt to reconnect.
// Let's not change the status of the tree node now.
if (!_wasConnected) {
tree.setInode(_item);
tree.addIcon(_item, {icon: 'icon-server-not-connected'});
}
alertify.pgNotifier('error', xhr, error, function(msg) {
setTimeout(function() {
alertify.dlgServerPass(
'{{ _('Connect to Server') }}',
msg, _node, _data, _tree, _item, _wasConnected
).resizeTo();
}, 100);
});
},
onSuccess = function(res, node, data, tree, item, _wasConnected) {
if (res && res.data) {
if (typeof res.data.icon == 'string') {
tree.removeIcon(item);
data.icon = res.data.icon;
tree.addIcon(item, {icon: data.icon});
}
_.extend(data, res.data);
data.is_connecting = false;
var serverInfo = pgBrowser.serverInfo =
pgBrowser.serverInfo || {};
serverInfo[data._id] = _.extend({}, data);
alertify.success(res.info);
obj.trigger('connected', obj, item, data);
// Generate the event that server is connected
pgBrowser.Events.trigger(
'pgadmin:server:connected', data._id, item, data
);
// Generate the event that database is connected
pgBrowser.Events.trigger(
'pgadmin:database:connected', data._id, data.db, item, data
);
// We're not reconnecting
if (!_wasConnected) {
tree.setInode(item);
tree.deselect(item);
setTimeout(function() {
tree.select(item);
tree.open(item);
}, 10);
} else {
// We just need to refresh the tree now.
setTimeout(function() {
node.callbacks.refresh.apply(node, [true]);
}, 10);
}
}
};
// Ask Password and send it back to the connect server
if (!alertify.dlgServerPass) {
alertify.dialog('dlgServerPass', function factory() {
return {
main: function(title, message, model, data, tree, item) {
main: function(
title, message, node, data, tree, item,
_status, _onSuccess, _onFailure, _onCancel
) {
this.set('title', title);
this.message = message;
this.tree = tree;
this.nodeData = data;
this.nodeItem = item;
this.nodeModel = model;
this.node= node;
this.connected = _status;
this.onSuccess = _onSuccess || onSuccess;
this.onFailure = _onFailure || onFailure;
this.onCancel = _onCancel || onCancel;
},
setup:function() {
return {
@ -791,18 +907,24 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
this.setContent(this.message);
},
callback: function(closeEvent) {
var _sdata = this.nodeData,
_tree = this.tree,
var _tree = this.tree,
_item = this.nodeItem,
_model = this.nodeModel;
_node = this.node,
_data = this.nodeData,
_status = this.connected,
_onSuccess = this.onSuccess,
_onFailure = this.onFailure,
_onCancel = this.onCancel;
if (closeEvent.button.text == "{{ _('OK') }}") {
var _url = _model.generate_url(_item, 'connect', _sdata, true);
var _url = _node.generate_url(_item, 'connect', _data, true);
_tree.setLeaf(_item);
_tree.removeIcon(_item);
_tree.addIcon(_item, {icon: 'icon-server-connecting'});
if (!_status) {
_tree.setLeaf(_item);
_tree.removeIcon(_item);
_tree.addIcon(_item, {icon: 'icon-server-connecting'});
}
$.ajax({
type: 'POST',
@ -810,38 +932,58 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
url: _url,
data: $('#frmPassword').serialize(),
success: function(res) {
return onSuccess(
res, _model, _sdata, _tree, _item
return _onSuccess(
res, _node, _data, _tree, _item, _status
);
},
error: function(xhr, status, error) {
return onFailure(
xhr, status, error, _model, _sdata, _tree, _item
return _onFailure(
xhr, status, error, _node, _data, _tree, _item, _status
);
}
});
} else {
_tree.setInode(_item);
_tree.removeIcon(_item);
_tree.addIcon(_item, {icon: 'icon-server-not-connected'});
this.onCancel && typeof(this.onCancel) == 'function' &&
this.onCancel(_tree, _item, _data, _status);
}
}
};
});
}
var onCancel = function(_tree, _item, _data, _status) {
_data.is_connecting = false;
_tree.unload(_item);
_tree.setInode(_item);
_tree.removeIcon(_item);
_tree.addIcon(_item, {icon: 'icon-server-not-connected'});
obj.trigger('connect:cancelled', data._id, data.db, obj, _item, _data);
pgBrowser.Events.trigger(
'pgadmin:server:connect:cancelled', data._id, _item, _data, obj
);
pgBrowser.Events.trigger(
'pgadmin:database:connect:cancelled', data._id, data.db, _item, _data, obj
);
if (_status) {
_tree.select(_item);
}
};
data.is_connecting = true;
url = obj.generate_url(item, "connect", data, true);
$.post(url)
.done(
function(res) {
if (res.success == 1) {
return onSuccess(res, obj, data, tree, item);
}
})
.fail(
function(xhr, status, error) {
return onFailure(xhr, status, error, obj, data, tree, item);
});
.done(function(res) {
if (res.success == 1) {
return onSuccess(
res, obj, data, tree, item, wasConnected
);
}
})
.fail(function(xhr, status, error) {
return onFailure(
xhr, status, error, obj, data, tree, item, wasConnected
);
});
}
/* Send PING to indicate that session is alive */

View File

@ -1,8 +1,8 @@
SELECT
procpid AS "{{ conn|qtIdent('PID') }},
usename AS "{{ conn|qtIdent(_('User')|safe) }},
datname AS "{{ conn|qtIdent(_('Database')|safe) }},
backend_start AS "{{ conn|qtIdent(_('Backend start')|safe) }},
procpid AS {{ conn|qtIdent('PID') }},
usename AS {{ conn|qtIdent(_('User')) }},
datname AS {{ conn|qtIdent(_('Database')) }},
backend_start AS {{ conn|qtIdent(_('Backend start')) }},
CASE
WHEN client_hostname IS NOT NULL AND client_hostname != '' THEN
client_hostname || ':' || client_port
@ -12,22 +12,22 @@ SELECT
'local pipe'
ELSE
'localhost:' || client_port
END AS "{{ conn|qtIdent(_('Client')|safe) }},
application_name AS "{{ conn|qtIdent(_('Application')|safe) }},
waiting AS "{{ conn|qtIdent(_('Waiting?')|safe) }},
current_query AS "{{ conn|qtIdent(_('Query')|safe) }},
query_start AS "{{ conn|qtIdent(_('Query start')|safe) }},
xact_start AS "{{ conn|qtIdent(_('Xact start')|safe) }}
END AS {{ conn|qtIdent(_('Client')) }},
application_name AS {{ conn|qtIdent(_('Application')) }},
waiting AS {{ conn|qtIdent(_('Waiting?')) }},
current_query AS {{ conn|qtIdent(_('Query')) }},
query_start AS {{ conn|qtIdent(_('Query start')) }},
xact_start AS {{ conn|qtIdent(_('Xact start')) }}
FROM
pg_stat_activity sa
WHERE
(SELECT r.rolsuper OR r.oid = sa.usesysid FROM pg_roles r WHERE r.rolname = current_user)
UNION
SELECT
procpid AS "{{ conn|qtIdent('PID') }},
usename AS "{{ conn|qtIdent(_('User')|safe) }},
'' AS "{{ conn|qtIdent(_('Database')|safe) }},
backend_start AS "{{ conn|qtIdent(_('Backend start')|safe) }},
procpid AS "PID",
usename AS {{ conn|qtIdent(_('User')) }},
datname AS {{ conn|qtIdent(_('Database')) }},
backend_start AS {{ conn|qtIdent(_('Backend start')) }},
CASE
WHEN client_hostname IS NOT NULL AND client_hostname != '' THEN
client_hostname || ':' || client_port
@ -37,12 +37,12 @@ SELECT
'local pipe'
ELSE
'localhost:' || client_port
END AS "{{ conn|qtIdent(_('Client')|safe) }},
{{ _('Streaming Replication') }}|safe|qtLiteral AS "{{ conn|qtIdent(_('Application')|safe) }},
null AS "{{ conn|qtIdent(_('Waiting?')|safe) }},
state || ' [sync (state: ' || COALESCE(sync_state, '') || ', priority: ' || sync_priority::text || ')] (' || sent_location || ' sent, ' || write_location || ' written, ' || flush_location || ' flushed, ' || replay_location || ' applied)' AS "{{ conn|qtIdent(_('Query')|safe) }},
null AS "{{ conn|qtIdent(_('Query start')|safe) }},
null AS "{{ conn|qtIdent(_('Xact start')|safe) }}
END AS {{ conn|qtIdent(_('Client')) }},
{{ _('Streaming Replication') }}|qtLiteral AS {{ conn|qtIdent(_('Application')) }},
null AS {{ conn|qtIdent(_('Waiting?')) }},
state || ' [sync (state: ' || COALESCE(sync_state, '') || ', priority: ' || sync_priority::text || ')] (' || sent_location || ' sent, ' || write_location || ' written, ' || flush_location || ' flushed, ' || replay_location || ' applied)' AS {{ conn|qtIdent(_('Query')) }},
null AS {{ conn|qtIdent(_('Query start')) }},
null AS {{ conn|qtIdent(_('Xact start')) }}
FROM
pg_stat_replication sa
WHERE

View File

@ -1,8 +1,8 @@
SELECT
pid AS {{ conn|qtIdent('PID') }},
usename AS {{ conn|qtIdent(_('User')|safe) }},
datname AS {{ conn|qtIdent(_('Database')|safe) }},
backend_start AS {{ conn|qtIdent(_('Backend start')|safe) }},
pid AS "PID",
usename AS {{ conn|qtIdent(_('User')) }},
datname AS {{ conn|qtIdent(_('Database')) }},
backend_start AS {{ conn|qtIdent(_('Backend start')) }},
CASE
WHEN client_hostname IS NOT NULL AND client_hostname != '' THEN
client_hostname || ':' || client_port
@ -12,22 +12,22 @@ SELECT
'local pipe'
ELSE
'localhost:' || client_port
END AS {{ conn|qtIdent(_('Client')|safe) }},
application_name AS {{ conn|qtIdent(_('Application')|safe) }},
waiting AS {{ conn|qtIdent(_('Waiting?')|safe) }},
query AS {{ conn|qtIdent(_('Query')|safe) }},
query_start AS {{ conn|qtIdent(_('Query start')|safe) }},
xact_start AS {{ conn|qtIdent(_('Xact start')|safe) }}
END AS {{ conn|qtIdent(_('Client')) }},
application_name AS {{ conn|qtIdent(_('Application')) }},
waiting AS {{ conn|qtIdent(_('Waiting?')) }},
query AS {{ conn|qtIdent(_('Query')) }},
query_start AS {{ conn|qtIdent(_('Query start')) }},
xact_start AS {{ conn|qtIdent(_('Xact start')) }}
FROM
pg_stat_activity sa
WHERE
(SELECT r.rolsuper OR r.oid = sa.usesysid FROM pg_roles r WHERE r.rolname = current_user)
UNION
SELECT
pid AS {{ conn|qtIdent('PID') }},
usename AS {{ conn|qtIdent(_('User')|safe) }},
'' AS {{ conn|qtIdent(_('Database')|safe) }},
backend_start AS {{ conn|qtIdent(_('Backend start')|safe) }},
pid AS "PID",
usename AS {{ conn|qtIdent(_('User')) }},
'' AS {{ conn|qtIdent(_('Database')) }},
backend_start AS {{ conn|qtIdent(_('Backend start')) }},
CASE
WHEN client_hostname IS NOT NULL AND client_hostname != '' THEN
client_hostname || ':' || client_port
@ -37,12 +37,12 @@ SELECT
'local pipe'
ELSE
'localhost:' || client_port
END AS {{ conn|qtIdent(_('Client')|safe) }},
{{ _('Streaming Replication')|safe|qtLiteral }} AS {{ conn|qtIdent(_('Application')|safe) }},
null AS {{ conn|qtIdent(_('Waiting?')|safe) }},
state || ' [sync (state: ' || COALESCE(sync_state, '') || ', priority: ' || sync_priority::text || ')] (' || sent_location || ' sent, ' || write_location || ' written, ' || flush_location || ' flushed, ' || replay_location || ' applied)' AS {{ conn|qtIdent(_('Query')|safe) }},
null AS {{ conn|qtIdent(_('Query start')|safe) }},
null AS {{ conn|qtIdent(_('Xact start')|safe) }}
END AS {{ conn|qtIdent(_('Client')) }},
{{ _('Streaming Replication')|qtLiteral }} AS {{ conn|qtIdent(_('Application')) }},
null AS {{ conn|qtIdent(_('Waiting?')) }},
state || ' [sync (state: ' || COALESCE(sync_state, '') || ', priority: ' || sync_priority::text || ')] (' || sent_location || ' sent, ' || write_location || ' written, ' || flush_location || ' flushed, ' || replay_location || ' applied)' AS {{ conn|qtIdent(_('Query')) }},
null AS {{ conn|qtIdent(_('Query start')) }},
null AS {{ conn|qtIdent(_('Xact start')) }}
FROM
pg_stat_replication sa
WHERE

View File

@ -335,7 +335,11 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) {
url: '{{ url_for('browser.get_nodes') }}',
converters: {
'text json': function(payload) {
data = JSON.parse(payload).data;
data = JSON.parse(payload).data.sort(function(a, b) {
return (
(a.label === b.label) ? 0 : (a.label < b.label ? -1 : 1)
);
});
_.each(data, function(d){
d.label = _.escape(d.label);
})

View File

@ -114,14 +114,24 @@ function($, _, S, pgAdmin, Backbone, Alertify, Backform) {
// Fetch Data
collection.fetch({reset: true})
.error(function(jqxhr, error, message) {
.error(function(xhr, error, message) {
pgBrowser.Events.trigger(
'pgadmin:collection:retrieval:error', 'properties', xhr, error, message, item, that
);
if (
!Alertify.pgHandleItemError(xhr, error, message, {item: item, info: info})
) {
Alertify.pgNotifier(
error, jqxhr,
error, xhr,
S(
"{{ _("Error retrieving properties: %s.") }}"
).sprintf(message).value()
);
});
"{{ _("Error retrieving properties- %s") }}"
).sprintf(message || that.label).value(),
function() {
console.log(arguments);
}
);
}
});
},
generate_url: function(item, type, d) {
var url = pgAdmin.Browser.URL + '{TYPE}/{REDIRECT}{REF}',

View File

@ -14,8 +14,8 @@ function(_, S, pgAdmin) {
'SQL_TAB': '{{ _('SQL') }}',
'SQL_INCOMPLETE': '{{ _('Incomplete definition') }}',
'SQL_NO_CHANGE': '{{ _('Nothing changed')|safe }}',
'MUST_BE_INT' : "{{ _("'%s' must be an integer.")|safe }}",
'MUST_BE_NUM' : "{{ _("'%s' must be a numeric.")|safe }}",
'MUST_BE_INT' : "{{ _("'%s' must be an integer.") }}",
'MUST_BE_NUM' : "{{ _("'%s' must be a numeric.") }}",
'MUST_GR_EQ' : "{{ _("'%s' must be greater than or equal to %d.")|safe }}",
'MUST_LESS_EQ' : "{{ _("'%s' must be less than or equal to %d.")|safe }}",
'STATISTICS_LABEL': "{{ _("Statistics") }}",
@ -24,12 +24,13 @@ function(_, S, pgAdmin) {
'NODE_HAS_NO_STATISTICS': "{{ _("No statistics are available for the selected object.") }}",
'TRUE': "{{ _("True") }}",
'FALSE': "{{ _("False") }}",
'NOTE_CTRL_LABEL': "{{ _("Note") }}"
'NOTE_CTRL_LABEL': "{{ _("Note") }}",
'ERR_RETRIEVAL_INFO': "{{ _("Error retrieving the information- %s") }}",
'CONNECTION_LOST': "{{ _("Connection to the server has been lost!") }}"
};
{% for key in current_app.messages.keys() %}
messages['{{ key|safe }}'] = '{{ current_app.messages[key]|safe }}';
messages['{{ key }}'] = '{{ current_app.messages[key] }}';
{% endfor %}
return pgBrowser.messages;

View File

@ -36,6 +36,14 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
// Make sure - a child have all the callbacks of the parent.
child.callbacks = _.extend({}, parent.callbacks, props.callbacks);
var bindToChild = function(cb) {
if (typeof(child.callbacks[cb]) == 'function') {
child.callbacks[cb] = child.callbacks[cb].bind(child);
}
},
callbacks = _.keys(child.callbacks);
for(var idx = 0; idx < callbacks.length; idx++) bindToChild(callbacks[idx]);
// Registering the node by calling child.Init(...) function
child.Init.apply(child);
@ -174,7 +182,7 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
//
// Used to generate view for the particular node properties, edit,
// creation.
getView: function(item, type, el, node, formType, callback, ctx) {
getView: function(item, type, el, node, formType, callback, ctx, cancelFunc) {
var that = this;
if (!this.type || this.type == '')
@ -265,24 +273,43 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
if (!newModel.isNew()) {
// This is definetely not in create mode
newModel.fetch()
.success(function(res, msg, xhr) {
// We got the latest attributes of the
// object. Render the view now.
view.render();
if (type != 'properties') {
$(el).focus();
}
newModel.startNewSession();
})
.error(function(jqxhr, error, message) {
// TODO:: We may not want to continue from here
.success(function(res, msg, xhr) {
// We got the latest attributes of the
// object. Render the view now.
view.render();
if (type != 'properties') {
$(el).focus();
}
newModel.startNewSession();
})
.error(function(xhr, error, message) {
var _label = that && item ?
that.getTreeNodeHierarchy(item)[that.type].label :
'';
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'properties',
xhr, error, message, item
);
if (
!Alertify.pgHandleItemError(
xhr, error, message, {item: item, info: info}
)
) {
Alertify.pgNotifier(
error, jqxhr,
error, xhr,
S(
"{{ _("Error retrieving properties: %s.") }}"
).sprintf(message).value()
);
});
"{{ _("Error retrieving properties- %s") }}"
).sprintf(message || _label).value(),
function() {
console.log(arguments);
}
);
}
// Close the panel (if couldn't fetch properties)
if (cancelFunc) {
cancelFunc();
}
});
} else {
// Yay - render the view now!
$(el).focus();
@ -1039,7 +1066,7 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
};
// Create a view to edit/create the properties in fieldsets
view = that.getView(item, action, content, data, 'dialog', updateButtons, j);
view = that.getView(item, action, content, data, 'dialog', updateButtons, j, onCancelFunc);
if (view) {
// Save it to release it later
j.data('obj-view', view);

View File

@ -1,6 +1,7 @@
define(
['underscore', 'underscore.string', 'jquery', 'pgadmin.browser'],
function(_, S, $, pgBrowser) {
define([
'underscore', 'underscore.string', 'jquery', 'pgadmin.browser',
'alertify', 'pgadmin.alertifyjs'
], function(_, S, $, pgBrowser, Alertify) {
if (pgBrowser.ShowNodeDepends)
return pgBrowser.ShowNodeDepends;
@ -226,7 +227,30 @@ define(
$gridContainer.removeClass('hidden');
// Set the url, fetch the data and update the collection
collection.url = url;
collection.fetch({ reset: true });
collection.fetch({
reset: true,
error: function(coll, xhr, error, message) {
var _label = treeHierarchy[n_type].label;
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'depends', xhr, status, error
);
if (
!Alertify.pgHandleItemError(xhr, error, message, {
item: item, info: treeHierarchy
})
) {
Alertify.pgNotifier(
status, xhr,
S(
pgBrowser.messages['ERR_RETRIEVAL_INFO']
).sprintf(message || _label).value(),
function() {
console.log(arguments);
}
);
}
}
});
}
}
if (msg != '') {

View File

@ -1,6 +1,7 @@
define(
['underscore', 'jquery', 'pgadmin.browser'],
function(_, $, pgBrowser) {
define([
'underscore', 'underscore.string', 'jquery', 'pgadmin.browser',
'alertify', 'pgadmin.alertifyjs'
], function(_, S, $, pgBrowser, Alertify) {
pgBrowser.ShowNodeSQL = pgBrowser.ShowNodeSQL || {};
@ -84,8 +85,26 @@ function(_, $, pgBrowser) {
pgAdmin.Browser.editor.setValue(res);
}
},
error: function() {
// TODO:: Report this
error: function(xhr, error, message) {
var _label = treeHierarchy[n_type].label;
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'sql', xhr, status, error, item
);
if (
!Alertify.pgHandleItemError(xhr, error, message, {
item: item, info: treeHierarchy
})
) {
Alertify.pgNotifier(
status, xhr,
S(
pgBrowser.messages['ERR_RETRIEVAL_INFO']
).sprintf(message || _label).value(),
function() {
console.log(arguments);
}
);
}
}
});
}

View File

@ -1,6 +1,7 @@
define(
['underscore', 'jquery', 'pgadmin.browser', 'backgrid', 'wcdocker', 'pgadmin.backgrid'],
function(_, $, pgBrowser, Backgrid) {
define([
'underscore', 'underscore.string', 'jquery', 'pgadmin.browser', 'backgrid',
'alertify', 'wcdocker', 'pgadmin.backgrid', 'pgadmin.alertifyjs'
], function(_, S, $, pgBrowser, Backgrid, Alertify) {
if (pgBrowser.NodeStatistics)
return pgBrowser.NodeStatistics;
@ -210,8 +211,26 @@ function(_, $, pgBrowser, Backgrid) {
$msgContainer.removeClass('hidden');
}
},
error: function() {
// TODO:: Report this error.
error: function(xhr, error, message) {
var _label = treeHierarchy[n_type].label;
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'statistics', xhr, status, error, item
);
if (
!Alertify.pgHandleItemError(xhr, error, message, {
item: item, info: treeHierarchy
})
) {
Alertify.pgNotifier(
status, xhr,
S(
pgBrowser.messages['ERR_RETRIEVAL_INFO']
).sprintf(message || _label).value(),
function() {
console.log(arguments);
}
);
}
}
});
}

View File

@ -95,7 +95,7 @@ function(alertify, S) {
if (contentType) {
try {
if (contentType.indexOf('text/json') == 0) {
if (contentType.indexOf('application/json') == 0) {
resp = $.parseJSON(msg);
if (resp.result != null && (!resp.errormsg || resp.errormsg == '') &&
@ -104,17 +104,19 @@ function(alertify, S) {
}
msg = _.escape(resp.result) || _.escape(resp.errormsg) || "Unknown error";
}
} catch (exc) {
}
if (contentType.indexOf('text/html') == 0) {
alertify.notify(
if (contentType.indexOf('text/html') == 0) {
alertify.notify(
S(
'%s<br><br>' + window.pgAdmin.Browser.messages.CLICK_FOR_DETAILED_MSG
).sprintf(promptmsg).value(), type, 0, function() {
alertify.pgIframeDialog().show().set({ frameless: false }).set('pg_msg', msg);
'%s<br><br>' +
window.pgAdmin.Browser.messages.CLICK_FOR_DETAILED_MSG
).sprintf(promptmsg).value(), type, 0, function() {
alertify.pgIframeDialog().show().set({frameless: false}).set(
'pg_msg', msg
);
});
return;
return;
}
} catch (exc) {
}
}
alertify.alert().show().set(
@ -185,4 +187,125 @@ function(alertify, S) {
this.set('onrestored', alertifyDialogResized);
};
alertify.pgHandleItemError = function(xhr, error, message, args) {
var pgBrowser = window.pgAdmin.Browser;
if (!xhr || !pgBrowser) {
return;
}
var msg = xhr.responseText,
contentType = xhr.getResponseHeader('Content-Type'),
msg = xhr.responseText,
jsonResp = contentType &&
contentType.indexOf('application/json') == 0 &&
$.parseJSON(xhr.responseText);
if (
jsonResp && (
xhr.status == 503 ? (
jsonResp.info == 'CONNECTION_LOST' &&
'server' in args.info && jsonResp.data.sid >= 0 &&
jsonResp.data.sid == args.info.server._id
) : (
xhr.status == 428 &&
jsonResp.errormsg &&
jsonResp.errormsg == pgBrowser.messages.CONNECTION_LOST
)
)
) {
if (
args.preHandleConnectionLost &&
typeof(args.preHandleConnectionLost) == 'function'
) {
args.preHandleConnectionLost.apply(this, arguments);
}
// Check the status of the maintenance server connection.
var server = pgBrowser.Nodes['server'],
ctx = {
resp: jsonResp,
xhr: xhr,
args: args
},
reconnectServer = function() {
var ctx = this,
onServerConnect = function(_sid, _i, _d) {
// Yay - server is reconnected.
if (this.args.info.server._id == _sid) {
pgBrowser.Events.off(
'pgadmin:server:connected', onServerConnect
);
pgBrowser.Events.off(
'pgadmin:server:connect:cancelled', onConnectCancel
);
// Do we need to connect the disconnected server now?
if (
this.resp.data.database &&
this.resp.data.database != _d.db
) {
// Server is connected now, we will need to inform the
// database to connect it now.
pgBrowser.Events.trigger(
'pgadmin:database:connection:lost', this.args.item,
this.resp, true
);
}
}
}.bind(ctx),
onConnectCancel = function(_sid, _item, _data) {
// User has cancelled the operation in between.
if (_sid == this.args.info.server.id) {
pgBrowser.Events.off('pgadmin:server:connected', onServerConnect);
pgBrowser.Events.off('pgadmin:server:connect:cancelled', onConnectCancel);
// Connection to the database will also be cancelled
pgBrowser.Events.trigger(
'pgadmin:database:connect:cancelled', _sid,
this.resp.data.database || _data.db, _item, _data
);
}
}.bind(ctx);
pgBrowser.Events.on('pgadmin:server:connected', onServerConnect);
pgBrowser.Events.on('pgadmin:server:connect:cancelled', onConnectCancel);
// Connection to the server has been lost, we need to inform the
// server first to take the action first.
pgBrowser.Events.trigger(
'pgadmin:server:connection:lost', this.args.item, this.resp
);
}.bind(ctx);
$.ajax({
url: server.generate_url(
null, 'connect', args.info.server, true, args.info
),
dataType: 'json',
success: function(res) {
if (res.success && 'connected' in res.data) {
if (res.data.connected) {
// Server is connected, but - the connection with the
// particular database has been lost.
pgBrowser.Events.trigger(
'pgadmin:database:connection:lost', args.item, jsonResp
);
return;
}
}
// Serever was not connected, we should first try to connect
// the server.
reconnectServer();
},
error: function() {
reconnectServer();
}
});
return true;
}
return false;
};
});

View File

@ -30,8 +30,9 @@ class DataTypeJSONEncoder(json.JSONEncoder):
return json.JSONEncoder.default(self, obj)
def make_json_response(success=1, errormsg='', info='', result=None,
data=None, status=200):
def make_json_response(
success=1, errormsg='', info='', result=None, data=None, status=200
):
"""Create a HTML response document describing the results of a request and
containing the data."""
doc = dict()
@ -44,7 +45,7 @@ def make_json_response(success=1, errormsg='', info='', result=None,
return Response(
response=json.dumps(doc, cls=DataTypeJSONEncoder),
status=status,
mimetype="text/json"
mimetype="application/json"
)
@ -53,7 +54,7 @@ def make_response(response=None, status=200):
return Response(
response=json.dumps(response, cls=DataTypeJSONEncoder),
status=status,
mimetype="text/json"
mimetype="application/json"
)
@ -120,10 +121,25 @@ def gone(errormsg=''):
)
def not_implemented(errormsg=_('Not implemented.')):
def not_implemented(errormsg=_('Not implemented.'), info='', result=None, data=None):
"""Create a response with HTTP status code 501 - Not Implemented."""
return make_json_response(
status=501,
success=0,
errormsg=errormsg
errormsg=errormsg,
info=info,
result=result,
data=data
)
def service_unavailable(errormsg=_("Service Unavailable"), info='', result=None, data=None):
"""Create a response with HTTP status code 503 - Server Unavailable."""
return make_json_response(
status=503,
success=0,
errormsg=errormsg,
info=info,
result=result,
data=data
)

View File

@ -30,6 +30,7 @@ from psycopg2.extensions import adapt
import config
from pgadmin.model import Server, User
from pgadmin.utils.exception import ConnectionLost
from .keywords import ScanKeyword
from ..abstract import BaseDriver, BaseConnection
from .cursor import DictCursor
@ -179,6 +180,7 @@ class Connection(BaseConnection):
self.execution_aborted = False
self.row_count = 0
self.__notices = None
self.password = None
super(Connection, self).__init__()
@ -225,10 +227,13 @@ class Connection(BaseConnection):
password = None
mgr = self.manager
if 'password' in kwargs:
encpass = kwargs['password']
else:
encpass = getattr(mgr, 'password', None)
encpass = kwargs['password'] if 'password' in kwargs else None
if encpass is None:
encpass = self.password or getattr(mgr, 'password', None)
# Reset the existing connection password
self.password = None
if encpass:
# Fetch Logged in User Details.
@ -239,6 +244,10 @@ class Connection(BaseConnection):
try:
password = decrypt(encpass, user.password)
# password is in bytes, for python3 we need it in string
if isinstance(password, bytes):
password = password.decode()
except Exception as e:
current_app.logger.exception(e)
return False, \
@ -246,10 +255,6 @@ class Connection(BaseConnection):
str(e)
)
# password is in bytes, for python3 we need it in string
if isinstance(password, bytes):
password = password.decode()
try:
if hasattr(str, 'decode'):
database = self.db.encode('utf-8')
@ -401,11 +406,18 @@ WHERE
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:
raise ConnectionLost(
self.manager.sid,
self.db,
None if self.conn_id[0:3] == u'DB:' else self.conn_id[5:]
)
cur = getattr(g, "{0}#{1}".format(
self.manager.sid,
self.conn_id.encode('utf-8')
@ -475,7 +487,7 @@ Attempting to reconnect to the database server (#{server_id}) for the connection
Connection for server#{0} with database "{1}" was lost.
Attempt to reconnect it failed with the error:
{2}"""
).format(self.driver.server_id, self.database, cur)
).format(self.driver.server_id, self.db, cur)
current_app.logger.error(msg)
return False, cur
@ -593,6 +605,12 @@ Attempt to reconnect it failed with the error:
self.__internal_blocking_execute(cur, query, params)
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:]
)
errmsg = self._formatted_exception_msg(pe, formatted_exception_msg)
current_app.logger.error(
u"Failed to execute query (execute_scalar) for the server #{server_id} - {conn_id} (Query-id: {query_id}):\nError Message:{errmsg}".format(
@ -694,6 +712,12 @@ Failed to execute query (execute_async) for the server #{server_id} - {conn_id}
self.__internal_blocking_execute(cur, query, params)
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:]
)
errmsg = self._formatted_exception_msg(pe, formatted_exception_msg)
current_app.logger.error(u"""
Failed to execute query (execute_void) for the server #{server_id} - {conn_id}
@ -733,6 +757,12 @@ Failed to execute query (execute_void) for the server #{server_id} - {conn_id}
self.__internal_blocking_execute(cur, query, params)
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:]
)
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(
@ -778,6 +808,12 @@ Failed to execute query (execute_void) for the server #{server_id} - {conn_id}
self.__internal_blocking_execute(cur, query, params)
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:]
)
errmsg = self._formatted_exception_msg(pe, formatted_exception_msg)
current_app.logger.error(
u"Failed to execute query (execute_dict) for the server #{server_id}- {conn_id} (Query-id: {query_id}):\nError Message:{errmsg}".format(
@ -867,6 +903,7 @@ Failed to reset the connection to the server due to following error:
if self.conn:
self.conn.close()
self.conn = None
self.password = None
def _wait(self, conn):
"""
@ -942,6 +979,12 @@ Failed to reset the connection to the server due to following error:
try:
status = self._wait_timeout(self.conn, ASYNC_WAIT_TIMEOUT)
except psycopg2.Error as pe:
if cur.closed:
raise ConnectionLost(
self.manager.sid,
self.db,
self.conn_id[5:]
)
errmsg = self._formatted_exception_msg(pe, formatted_exception_msg)
return False, errmsg, None
@ -1242,10 +1285,6 @@ class ServerManager(object):
self, database=None, conn_id=None, auto_reconnect=True, did=None,
async=None
):
msg_active_conn = gettext(
"Server has no active connection. Please connect to the server."
)
if database is not None:
if hasattr(str, 'decode') and \
not isinstance(database, unicode):
@ -1285,7 +1324,7 @@ WHERE db.oid = {0}""".format(did))
))
if database is None:
raise Exception(msg_active_conn)
raise ConnectionLost(self.sid, None, None)
my_id = (u'CONN:{0}'.format(conn_id)) if conn_id is not None else \
(u'DB:{0}'.format(database))
@ -1387,6 +1426,13 @@ WHERE db.oid = {0}""".format(did))
return True
def _update_password(self, passwd):
self.password = passwd
for conn_id in self.connections:
conn = self.connections[conn_id]
if conn.conn is not None:
conn.password = passwd
def update_session(self):
managers = session['__pgsql_server_managers'] \
if '__pgsql_server_managers' in session else dict()

View File

@ -0,0 +1,42 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
from werkzeug.exceptions import HTTPException
from werkzeug.http import HTTP_STATUS_CODES
from flask_babel import gettext as _
from flask import request
from pgadmin.utils.ajax import service_unavailable
class ConnectionLost(HTTPException):
"""
Exception
"""
def __init__(self, _server_id, _database_name, _conn_id):
self.sid = _server_id
self.db = _database_name
self.conn_id = _conn_id
HTTPException.__init__(self)
@property
def name(self):
return HTTP_STATUS_CODES.get(505, 'Service Unavailable')
def get_response(self, environ=None):
return service_unavailable(
_("Connection to the server has been lost!"),
info="CONNECTION_LOST",
data={
'sid': self.sid,
'database': self.db,
'conn_id': self.conn_id
}
)