Backend changes to fetch the statistics for the database and server

nodes, along with the front-end changes for those node.

NOTE:
We've not yet added the support to show them on the front-end.
pull/3/head
Ashesh Vashi 2016-04-14 16:45:32 +05:30
parent 6f58170894
commit 8a39b3a700
14 changed files with 179 additions and 71 deletions

View File

@ -530,7 +530,32 @@ class ServerNode(PGChildNodeView):
return make_json_response(data='')
def statistics(self, gid, sid):
return make_json_response(data='')
from pgadmin.utils.driver import get_driver
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
conn = manager.connection()
if conn.connected():
status, res = conn.execute_dict(
render_template(
"/".join([
'servers/sql',
'9.2_plus' if manager.version >= 90200 else '9.1_plus',
'stats.sql'
]),
conn=conn, _=gettext
)
)
if not status:
return internal_server_error(errormsg=res)
return make_json_response(data=res)
return make_json_response(
info=gettext(
"Server has no active connection for generating statistics!"
)
)
def dependencies(self, gid, sid):
return make_json_response(data='')

View File

@ -148,8 +148,11 @@ 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']
SQL = render_template(
"/".join([self.template_path, 'properties.sql'])
"/".join([self.template_path, 'properties.sql']),
conn=self.conn, last_system_oid=last_system_oid
)
status, res = self.conn.execute_dict(SQL)
@ -164,8 +167,12 @@ class DatabaseView(PGChildNodeView):
@check_precondition(action="nodes")
def nodes(self, gid, sid):
res = []
last_system_oid = 0 if self.blueprint.show_system_objects else \
(self.manager.db_info[self.manager.did])['datlastsysoid']
SQL = render_template(
"/".join([self.template_path, 'nodes.sql'])
"/".join([self.template_path, 'nodes.sql']),
last_system_oid=last_system_oid
)
status, rset = self.conn.execute_dict(SQL)
@ -174,20 +181,20 @@ class DatabaseView(PGChildNodeView):
for row in rset['rows']:
if self.manager.db == row['name']:
connected=True
canDisConn=False
connected = True
canDisConn = False
else:
conn=self.manager.connection(row['name'])
connected=conn.connected()
canDisConn=True
conn = self.manager.connection(row['name'])
connected = conn.connected()
canDisConn = True
res.append(
self.blueprint.generate_browser_node(
row['did'],
sid,
row['name'],
icon="icon-database-not-connected" if not connected \
else "pg-icon-database",
icon="icon-database-not-connected" if not connected
else "pg-icon-database",
connected=connected,
tablespace=row['spcname'],
allowConn=row['datallowconn'],
@ -205,7 +212,7 @@ class DatabaseView(PGChildNodeView):
def node(self, gid, sid, did):
SQL = render_template(
"/".join([self.template_path, 'nodes.sql']),
did=did, conn=self.conn
did=did, conn=self.conn, last_system_oid=0
)
status, rset = self.conn.execute_2darray(SQL)
@ -240,7 +247,7 @@ class DatabaseView(PGChildNodeView):
def properties(self, gid, sid, did):
SQL = render_template(
"/".join([self.template_path, 'properties.sql']),
did=did, conn=self.conn
did=did, conn=self.conn, last_system_oid=0
)
status, res = self.conn.execute_dict(SQL)
@ -466,7 +473,7 @@ class DatabaseView(PGChildNodeView):
# We need oid of newly created database
SQL = render_template(
"/".join([self.template_path, 'properties.sql']),
name=data['name'], conn=self.conn
name=data['name'], conn=self.conn, last_system_oid=0
)
SQL = SQL.strip('\n').strip(' ')
if SQL and SQL != "":
@ -501,7 +508,9 @@ class DatabaseView(PGChildNodeView):
def update(self, gid, sid, did):
"""Update the database."""
data = request.form if request.form else json.loads(request.data.decode())
data = request.form if request.form else json.loads(
request.data.decode()
)
info = "nothing to update."
if did is not None:
@ -509,7 +518,7 @@ class DatabaseView(PGChildNodeView):
status, rset = self.conn.execute_dict(
render_template(
"/".join([self.template_path, 'nodes.sql']),
did=did, conn=self.conn
did=did, conn=self.conn, last_system_oid=0
)
)
if not status:
@ -646,7 +655,7 @@ class DatabaseView(PGChildNodeView):
status, rset = self.conn.execute_dict(
render_template(
"/".join([self.template_path, 'nodes.sql']),
did=did, conn=self.conn
did=did, conn=self.conn, last_system_oid=0
)
)
if not status:
@ -775,10 +784,12 @@ class DatabaseView(PGChildNodeView):
otherwise it will return statistics for all the databases in that
server.
"""
last_system_oid = 0 if self.blueprint.show_system_objects else \
(self.manager.db_info[self.manager.did])['datlastsysoid']
status, res = self.conn.execute_dict(
render_template(
"/".join([self.template_path, 'stats.sql']),
did=did, conn=self.conn
did=did, conn=self.conn, last_system_oid=last_system_oid
)
)
@ -786,7 +797,7 @@ class DatabaseView(PGChildNodeView):
return internal_server_error(errormsg=res)
return make_json_response(
data=res['rows'],
data=res,
status=200
)
@ -797,7 +808,7 @@ class DatabaseView(PGChildNodeView):
"""
SQL = render_template(
"/".join([self.template_path, 'properties.sql']),
did=did, conn=self.conn
did=did, conn=self.conn, last_system_oid=0
)
status, res = self.conn.execute_dict(SQL)
if not status:

View File

@ -11,7 +11,8 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
node: 'database',
label: '{{ _('Databases') }}',
type: 'coll-database',
columns: ['name', 'datowner', 'comments']
columns: ['name', 'datowner', 'comments'],
hasStatistics: true
});
};
@ -51,6 +52,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
sqlCreateHelp: 'sql-createdatabase.html',
hasSQL: true,
hasDepends: true,
hasStatistics: true,
canDrop: true,
label: '{{ _('Database') }}',
node_image: function() {

View File

@ -4,7 +4,9 @@ SELECT
FROM
pg_database db
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace = ta.oid{% if did %}
WHERE db.oid={{ did|qtLiteral }}::OID{% endif %}
WHERE {% if did %}
db.oid = {{ did|qtLiteral }}::OID{% else %}
db.oid > {{ last_system_oid }}::OID
{% endif %}
ORDER BY datname;

View File

@ -11,10 +11,10 @@ FROM pg_database db
LEFT OUTER JOIN pg_shdescription descr ON (
db.oid=descr.objoid AND descr.classoid='pg_database'::regclass
)
{% if did %}
WHERE db.oid= {{did}}::int
{% endif %}
{% if name %}
WHERE db.datname = {{name|qtLiteral}}
{% endif %}
ORDER BY datname
WHERE {% if did %}
db.oid = {{ did|qtLiteral }}::OID{% else %}{% if name %}
db.datname = {{ name|qtLiteral }}::text{% else %}
db.oid > {{ last_system_oid|qtLiteral }}::OID
{% endif %}{% endif %}
ORDER BY datname;

View File

@ -1,13 +1,28 @@
SELECT
db.datid as oid, db.datname, numbackends, xact_commit, xact_rollback, blks_read,
blks_hit, stats_reset, slave.confl_tablespace, slave.confl_lock,
slave.confl_snapshot, slave.confl_bufferpin, slave.confl_deadlock{% if has_size %},
pg_size_pretty(pg_database_size(db.datid)) as size
{% if not did %}db.datname AS {{ conn|qtIdent(_('Database')) }}, {% endif %}
numbackends AS {{ conn|qtIdent(_('Backends')) }},
xact_commit AS {{ conn|qtIdent(_('Xact Committed')) }},
xact_rollback AS {{ conn|qtIdent(_('Xact Rolled back')) }},
blks_read AS {{ conn|qtIdent(_('Blocks Read')) }},
blks_hit AS {{ conn|qtIdent(_('Blocks Hit')) }},
tup_returned AS {{ conn|qtIdent(_('Tuples Returned')) }},
tup_fetched AS {{ conn|qtIdent(_('Tuples Fetched')) }},
tup_inserted AS {{ conn|qtIdent(_('Tuples Inserted')) }},
tup_updated AS {{ conn|qtIdent(_('Tuples Updated')) }},
tup_deleted AS {{ conn|qtIdent(_('Tuples Deleted')) }},
stats_reset AS {{ conn|qtIdent(_('Last statistics reset')) }},
slave.confl_tablespace AS {{ conn|qtIdent(_('Tablespace conflicts')) }},
slave.confl_lock AS {{ conn|qtIdent(_('Lock conflicts')) }},
slave.confl_snapshot AS {{ conn|qtIdent(_('Snapshot conflicts')) }},
slave.confl_bufferpin AS {{ conn|qtIdent(_('Bufferpin conflicts')) }},
slave.confl_deadlock AS {{ conn|qtIdent(_('Deadlock conflicts')) }},
pg_size_pretty(pg_database_size(db.datid)) AS {{ conn|qtIdent(_('Size')) }}
FROM
pg_stat_database db
LEFT JOIN pg_stat_database_conflicts slave ON db.datid=slave.datid
{% if did %}
WHERE
did = {{ conn|qtIdent(did) }}::OID
WHERE {% if did %}
db.datid = {{ did|qtLiteral }}::OID{% else %}
db.datid > {{ last_system_oid|qtLiteral }}::OID
{% endif %}
ORDER BY db.datname;

View File

@ -3,8 +3,10 @@ SELECT
has_database_privilege(db.oid, 'CREATE') as cancreate, datdba as owner
FROM
pg_database db
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace = ta.oid{% if did %}
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace = ta.oid
WHERE {% if did %}
db.oid = {{ did|qtLiteral }}::OID{% else %}
db.oid > {{ last_system_oid }}::OID
{% endif %}
WHERE db.oid={{ did|qtLiteral }}::OID {% endif %}
ORDER BY datname;
ORDER BY datname;

View File

@ -12,10 +12,10 @@ FROM pg_database db
LEFT OUTER JOIN pg_shdescription descr ON (
db.oid=descr.objoid AND descr.classoid='pg_database'::regclass
)
{% if did %}
WHERE db.oid= {{did}}::int
{% endif %}
{% if name %}
WHERE db.datname = {{name|qtLiteral}}
{% endif %}
WHERE {% if did %}
db.oid = {{ did|qtLiteral }}::OID{% else %}{% if name %}
db.datname = {{ name|qtLiteral }}::text{% else %}
db.oid > {{ last_system_oid|qtLiteral }}::OID
{% endif %}{% endif %}
ORDER BY datname

View File

@ -1,13 +1,33 @@
SELECT
db.datid as oid, db.datname, numbackends, xact_commit, xact_rollback, blks_read,
blks_hit, stats_reset, slave.confl_tablespace, slave.confl_lock,
slave.confl_snapshot, slave.confl_bufferpin, slave.confl_deadlock{% if has_size %},
pg_size_pretty(pg_database_size(db.datid)) as size
{% if not did %}db.datname AS {{ conn|qtIdent(_('Database')) }}, {% endif %}
numbackends AS {{ conn|qtIdent(_('Backends')) }},
xact_commit AS {{ conn|qtIdent(_('Xact Committed')) }},
xact_rollback AS {{ conn|qtIdent(_('Xact Rolled back')) }},
blks_read AS {{ conn|qtIdent(_('Blocks Read')) }},
blks_hit AS {{ conn|qtIdent(_('Blocks Hit')) }},
tup_returned AS {{ conn|qtIdent(_('Tuples Returned')) }},
tup_fetched AS {{ conn|qtIdent(_('Tuples Fetched')) }},
tup_inserted AS {{ conn|qtIdent(_('Tuples Inserted')) }},
tup_updated AS {{ conn|qtIdent(_('Tuples Updated')) }},
tup_deleted AS {{ conn|qtIdent(_('Tuples Deleted')) }},
stats_reset AS {{ conn|qtIdent(_('Last statistics reset')) }},
slave.confl_tablespace AS {{ conn|qtIdent(_('Tablespace conflicts')) }},
slave.confl_lock AS {{ conn|qtIdent(_('Lock conflicts')) }},
slave.confl_snapshot AS {{ conn|qtIdent(_('Snapshot conflicts')) }},
slave.confl_bufferpin AS {{ conn|qtIdent(_('Bufferpin conflicts')) }},
slave.confl_deadlock AS {{ conn|qtIdent(_('Deadlock conflicts')) }},
temp_files AS {{ conn|qtIdent(_("Temporary files")) }},
pg_size_pretty(temp_bytes) AS {{ conn|qtIdent(_("Size of temporary files")) }},
deadlocks AS {{ conn|qtIdent(_("Deadlocks")) }},
blk_read_time AS {{ conn|qtIdent(_("Block read time")) }},
blk_write_time AS {{ conn|qtIdent(_("Block write time")) }},
pg_size_pretty(pg_database_size(db.datid)) AS {{ conn|qtIdent(_('Size')) }}
FROM
pg_stat_database db
LEFT JOIN pg_stat_database_conflicts slave ON db.datid=slave.datid
{% if did %}
WHERE
did = {{ conn|qtIdent(did) }}::OID
WHERE {% if did %}
db.datid = {{ did|qtLiteral }}::OID{% else %}
db.datid > {{ last_system_oid|qtLiteral }}::OID
{% endif %}
ORDER BY db.datname;

View File

@ -3,8 +3,10 @@ SELECT
has_database_privilege(db.oid, 'CREATE') as cancreate, datdba as owner
FROM
pg_database db
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace = ta.oid{% if did %}
WHERE db.oid={{ did|qtLiteral }}::OID{% endif %}
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace = ta.oid
WHERE {% if did %}
db.oid = {{ did|qtLiteral }}::OID{% else %}
db.oid > {{ last_system_oid }}::OID
{% endif %}
ORDER BY datname;

View File

@ -12,10 +12,10 @@ FROM pg_database db
LEFT OUTER JOIN pg_shdescription descr ON (
db.oid=descr.objoid AND descr.classoid='pg_database'::regclass
)
{% if did %}
WHERE db.oid= {{did}}::int
{% endif %}
{% if name %}
WHERE db.datname = {{name|qtLiteral}}
{% endif %}
WHERE {% if did %}
db.oid = {{ did|qtLiteral }}::OID{% else %}{% if name %}
db.datname = {{ name|qtLiteral }}::text{% else %}
db.oid > {{ last_system_oid|qtLiteral }}::OID
{% endif %}{% endif %}
ORDER BY datname

View File

@ -1,13 +1,33 @@
SELECT
db.datid as oid, db.datname, numbackends, xact_commit, xact_rollback, blks_read,
blks_hit, stats_reset, slave.confl_tablespace, slave.confl_lock,
slave.confl_snapshot, slave.confl_bufferpin, slave.confl_deadlock{% if has_size %},
pg_size_pretty(pg_database_size(db.datid)) as size
{% if not did %}db.datname AS {{ conn|qtIdent(_('Database')) }}, {% endif %}
numbackends AS {{ conn|qtIdent(_('Backends')) }},
xact_commit AS {{ conn|qtIdent(_('Xact Committed')) }},
xact_rollback AS {{ conn|qtIdent(_('Xact Rolled back')) }},
blks_read AS {{ conn|qtIdent(_('Blocks Read')) }},
blks_hit AS {{ conn|qtIdent(_('Blocks Hit')) }},
tup_returned AS {{ conn|qtIdent(_('Tuples Returned')) }},
tup_fetched AS {{ conn|qtIdent(_('Tuples Fetched')) }},
tup_inserted AS {{ conn|qtIdent(_('Tuples Inserted')) }},
tup_updated AS {{ conn|qtIdent(_('Tuples Updated')) }},
tup_deleted AS {{ conn|qtIdent(_('Tuples Deleted')) }},
stats_reset AS {{ conn|qtIdent(_('Last statistics reset')) }},
slave.confl_tablespace AS {{ conn|qtIdent(_('Tablespace conflicts')) }},
slave.confl_lock AS {{ conn|qtIdent(_('Lock conflicts')) }},
slave.confl_snapshot AS {{ conn|qtIdent(_('Snapshot conflicts')) }},
slave.confl_bufferpin AS {{ conn|qtIdent(_('Bufferpin conflicts')) }},
slave.confl_deadlock AS {{ conn|qtIdent(_('Deadlock conflicts')) }},
temp_files AS {{ conn|qtIdent(_("Temporary files")) }},
pg_size_pretty(temp_bytes) AS {{ conn|qtIdent(_("Size of temporary files")) }},
deadlocks AS {{ conn|qtIdent(_("Deadlocks")) }},
blk_read_time AS {{ conn|qtIdent(_("Block read time")) }},
blk_write_time AS {{ conn|qtIdent(_("Block write time")) }},
pg_size_pretty(pg_database_size(db.datid)) AS {{ conn|qtIdent(_('Size')) }}
FROM
pg_stat_database db
LEFT JOIN pg_stat_database_conflicts slave ON db.datid=slave.datid
{% if did %}
WHERE
did = {{ conn|qtIdent(did) }}::OID
WHERE {% if did %}
db.datid = {{ did|qtLiteral }}::OID{% else %}
db.datid > {{ last_system_oid|qtLiteral }}::OID
{% endif %}
ORDER BY db.datname;

View File

@ -8,6 +8,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
type: 'server',
label: '{{ _('Server') }}',
canDrop: true,
hasStatistics: true,
hasCollectiveStatistics: true,
Init: function() {
/* Avoid multiple registration of same menus */

View File

@ -12,7 +12,11 @@ function($, _, S, pgAdmin, Backbone, Alertify, Backform) {
if (pgBrowser.Collection)
return pgBrowser.Collection;
pgBrowser.Collection = _.extend(_.clone(pgBrowser.Node), {
pgBrowser.Collection = function() {};
_.extend(
pgBrowser.Collection,
_.clone(pgBrowser.Node), {
///////
// Initialization function
// Generally - used to register the menus for this type of node.
@ -34,6 +38,9 @@ function($, _, S, pgAdmin, Backbone, Alertify, Backform) {
}]);
},
hasId: false,
// A collection will always have a collection of statistics, when the node
// it represent will have some statistics.
hasCollectiveStatistics: true,
showProperties: function(item, data, panel) {
var that = this,
j = panel.$container.find('.obj_properties').first(),
@ -133,5 +140,5 @@ function($, _, S, pgAdmin, Backbone, Alertify, Backform) {
}
});
return pgAdmin.Browser.Collection;
return pgBrowser.Collection;
});