diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py index 99cf94a..95c8331 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py @@ -1295,6 +1295,35 @@ It may have been removed by another user or moved to another schema. return ajax_response(response=sql) + @check_precondition + def statistics(self, gid, sid, did, scid, fnid): + """ + Statistics + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + tid: Function/Procedure/Trigger Function Id + + Returns the statistics for a particular object if fnid is specified + """ + status, res = self.conn.execute_dict( + render_template( + "/".join([self.sql_template_path, 'stats.sql']), + conn=self.conn, fnid=fnid + ) + ) + + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + data=res, + status=200 + ) + FunctionView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/js/functions.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/js/functions.js index dc35d05..882066f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/js/functions.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/js/functions.js @@ -82,6 +82,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { collection_type: 'coll-function', hasSQL: true, hasDepends: true, + hasStatistics: true, hasScriptTypes: ['create', 'select'], parent_type: ['schema', 'catalog'], Init: function(args) { diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js index f3e0f45..24fc33a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js @@ -29,6 +29,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Function) { collection_type: 'coll-procedure', hasSQL: true, hasDepends: true, + hasStatistics: true, hasScriptTypes: ['create', 'exec'], parent_type: ['schema', 'catalog'], Init: function() { diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/js/trigger_functions.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/js/trigger_functions.js index c388bda..8f44f0d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/js/trigger_functions.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/js/trigger_functions.js @@ -25,6 +25,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { collection_type: 'coll-trigger_function', hasSQL: true, hasDepends: true, + hasStatistics: true, parent_type: ['schema', 'catalog'], Init: function(args) { /* Avoid mulitple registration of menus */ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/pg/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/pg/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/pg/sql/9.1_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/pg/sql/9.2_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/pg/sql/9.2_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/pg/sql/9.2_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/pg/sql/9.5_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/pg/sql/9.5_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/pg/sql/9.5_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/ppas/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/ppas/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/ppas/sql/9.1_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/ppas/sql/9.2_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/ppas/sql/9.2_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/ppas/sql/9.2_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/ppas/sql/9.5_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/ppas/sql/9.5_plus/stats.sql new file mode 100644 index 0000000..4f35c9a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/trigger_function/ppas/sql/9.5_plus/stats.sql @@ -0,0 +1,7 @@ +SELECT calls AS {{ conn|qtIdent(_('Number of calls')) }}, + total_time AS {{ conn|qtIdent(_('Total Time')) }}, + self_time AS {{ conn|qtIdent(_('Self Time')) }} +FROM + pg_stat_user_functions +WHERE + funcid = {{fnid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py index 9c746a9..ea04caf 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py @@ -688,5 +688,33 @@ class SequenceView(PGChildNodeView): status=200 ) + @check_precondition(action="stats") + def statistics(self, gid, sid, did, scid, seid): + """ + Statistics + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + seid: Sequence Id + + Returns the statistics for a particular object if seid is specified + """ + status, res = self.conn.execute_dict( + render_template( + "/".join([self.template_path, 'stats.sql']), + conn=self.conn, seid=seid + ) + ) + + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + data=res, + status=200 + ) SequenceView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js index d3755a4..b5ee220 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js @@ -24,6 +24,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { collection_type: 'coll-sequence', hasSQL: true, hasDepends: true, + hasStatistics: true, parent_type: ['schema', 'catalog'], Init: function() { /* Avoid mulitple registration of menus */ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..0c50e09 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/stats.sql @@ -0,0 +1,6 @@ +SELECT blks_read AS {{ conn|qtIdent(_('Blocks Read')) }}, + blks_hit AS {{ conn|qtIdent(_('Blocks Hit')) }} +FROM + pg_statio_all_sequences +WHERE + relid = {{ seid }}::OID \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py index b0b7e84..3acf709 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py @@ -233,7 +233,7 @@ class TableView(PGChildNodeView, DataTypeReader, VacuumSettings): 'nodes': [{'get': 'node'}, {'get': 'nodes'}], 'sql': [{'get': 'sql'}], 'msql': [{'get': 'msql'}, {'get': 'msql'}], - 'stats': [{'get': 'statistics'}], + 'stats': [{'get': 'statistics'}, {'get': 'statistics'}], 'dependency': [{'get': 'dependencies'}], 'dependent': [{'get': 'dependents'}], 'module.js': [{}, {}, {'get': 'module_js'}], @@ -2806,5 +2806,78 @@ class TableView(PGChildNodeView, DataTypeReader, VacuumSettings): return ajax_response(response=sql) + @check_precondition + def statistics(self, gid, sid, did, scid, tid=None): + """ + Statistics + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + tid: Table Id + + Returns the statistics for a particular table if tid is specified, + otherwise it will return statistics for all the tables in that + schema. + """ + + # Fetch schema name + status, schema_name = self.conn.execute_scalar( + render_template( + "/".join([self.template_path, 'get_schema.sql']), + conn=self.conn, scid=scid + ) + ) + if not status: + return internal_server_error(errormsg=schema_name) + + if tid is None: + status, res = self.conn.execute_dict( + render_template( + "/".join([self.template_path, 'coll_table_stats.sql']), + conn=self.conn, schema_name=schema_name + ) + ) + else: + # For Individual table stats + + # Check if pgstattuple extension is already created? + # if created then only add extended stats + status, is_pgstattuple = self.conn.execute_scalar(""" + SELECT (count(extname) > 0) AS is_pgstattuple + FROM pg_extension + WHERE extname='pgstattuple' + """) + if not status: + return internal_server_error(errormsg=is_pgstattuple) + + # Fetch Table name + status, table_name = self.conn.execute_scalar( + render_template( + "/".join([self.template_path, 'get_table.sql']), + conn=self.conn, scid=scid, tid=tid + ) + ) + if not status: + return internal_server_error(errormsg=table_name) + + status, res = self.conn.execute_dict( + render_template( + "/".join([self.template_path, 'stats.sql']), + conn=self.conn, schema_name=schema_name, + table_name=table_name, + is_pgstattuple=is_pgstattuple, tid=tid + ) + ) + + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + data=res, + status=200 + ) TableView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/__init__.py index 6e77b2e..236e284 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/__init__.py @@ -902,5 +902,47 @@ class ColumnsView(PGChildNodeView, DataTypeReader): status=200 ) + @check_precondition + def statistics(self, gid, sid, did, scid, tid, clid): + """ + Statistics + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + seid: Sequence Id + + Returns the statistics for a particular object if seid is specified + """ + # Fetch column name + SQL = render_template("/".join([self.template_path, + 'properties.sql']), tid=tid, clid=clid + , show_sys_objects=self.blueprint.show_system_objects) + + status, res = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + + data = dict(res['rows'][0]) + column = data['name'] + + status, res = self.conn.execute_dict( + render_template( + "/".join([self.template_path, 'stats.sql']), + conn=self.conn, schema=self.schema, + table=self.table, column=column + ) + ) + + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + data=res, + status=200 + ) + ColumnsView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/templates/column/js/column.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/templates/column/js/column.js index 94d5f9c..a2a0413 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/templates/column/js/column.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/templates/column/js/column.js @@ -81,6 +81,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) { } }, hasDepends: true, + hasStatistics: true, Init: function() { /* Avoid mulitple registration of menus */ if (this.initialized) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py index cf599e5..8b194c1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py @@ -814,6 +814,62 @@ class ExclusionConstraintView(PGChildNodeView): except Exception as e: return internal_server_error(errormsg=str(e)) + @check_precondition + def statistics(self, gid, sid, did, scid, tid, exid): + """ + Statistics + + Args: + gid: Server Group ID + sid: Server ID + did: Database ID + scid: Schema ID + tid: Table ID + cid: Exclusion constraint ID + + Returns the statistics for a particular object if cid is specified + """ + + # Check if pgstattuple extension is already created? + # if created then only add extended stats + status, is_pgstattuple = self.conn.execute_scalar(""" + SELECT (count(extname) > 0) AS is_pgstattuple + FROM pg_extension + WHERE extname='pgstattuple' + """) + if not status: + return internal_server_error(errormsg=is_pgstattuple) + + if is_pgstattuple: + # Fetch index details only if extended stats available + SQL = render_template( + "/".join([self.template_path, 'properties.sql']), + tid=tid, conn=self.conn, cid=exid) + status, result = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=result) + + data = result['rows'][0] + name = data['name'] + else: + name = None + + status, res = self.conn.execute_dict( + render_template( + "/".join([self.template_path, 'stats.sql']), + conn=self.conn, schema=self.schema, + name=name, exid=exid, is_pgstattuple=is_pgstattuple + ) + ) + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + data=res, + status=200 + ) + + constraint = ConstraintRegistry( 'exclusion_constraint', ExclusionConstraintModule, ExclusionConstraintView ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/templates/exclusion_constraint/js/exclusion_constraint.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/templates/exclusion_constraint/js/exclusion_constraint.js index c65dbf4..4ede14e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/templates/exclusion_constraint/js/exclusion_constraint.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/templates/exclusion_constraint/js/exclusion_constraint.js @@ -608,6 +608,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) { canDrop: true, canDropCascade: true, hasDepends: true, + hasStatistics: true, Init: function() { /* Avoid multiple registration of menus */ if (this.initialized) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py index 471a71e..212f88f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py @@ -845,6 +845,62 @@ class IndexConstraintView(PGChildNodeView): except Exception as e: return internal_server_error(errormsg=str(e)) + @check_precondition + def statistics(self, gid, sid, did, scid, tid, cid): + """ + Statistics + + Args: + gid: Server Group ID + sid: Server ID + did: Database ID + scid: Schema ID + tid: Table ID + cid: Primary key/Unique constraint ID + + Returns the statistics for a particular object if cid is specified + """ + + # Check if pgstattuple extension is already created? + # if created then only add extended stats + status, is_pgstattuple = self.conn.execute_scalar(""" + SELECT (count(extname) > 0) AS is_pgstattuple + FROM pg_extension + WHERE extname='pgstattuple' + """) + if not status: + return internal_server_error(errormsg=is_pgstattuple) + + if is_pgstattuple: + # Fetch index details only if extended stats available + sql = render_template("/".join([self.template_path, 'properties.sql']), + tid=tid, + cid=cid, + constraint_type= self.constraint_type) + status, res = self.conn.execute_dict(sql) + + if not status: + return internal_server_error(errormsg=res) + + result = res['rows'][0] + name = result['name'] + else: + name = None + + status, res = self.conn.execute_dict( + render_template( + "/".join([self.template_path, 'stats.sql']), + conn=self.conn, schema=self.schema, + name=name, cid=cid, is_pgstattuple=is_pgstattuple + ) + ) + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + data=res, + status=200 + ) class PrimaryKeyConstraintView(IndexConstraintView): node_type = 'primary_key' diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/templates/index_constraint/js/index_constraint.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/templates/index_constraint/js/index_constraint.js index 8cc52f8..1e45cad 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/templates/index_constraint/js/index_constraint.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/templates/index_constraint/js/index_constraint.js @@ -18,6 +18,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { {% endif %} hasSQL: true, hasDepends: false, + hasStatistics: true, parent_type: 'table', canDrop: true, canDropCascade: true, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py index e80e7d2..3238e02 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py @@ -200,7 +200,7 @@ class IndexesView(PGChildNodeView): 'nodes': [{'get': 'node'}, {'get': 'nodes'}], 'sql': [{'get': 'sql'}], 'msql': [{'get': 'msql'}, {'get': 'msql'}], - 'stats': [{'get': 'statistics'}], + 'stats': [{'get': 'statistics'}, {'get': 'statistics'}], 'dependency': [{'get': 'dependencies'}], 'dependent': [{'get': 'dependents'}], 'module.js': [{}, {}, {'get': 'module_js'}], @@ -871,4 +871,74 @@ class IndexesView(PGChildNodeView): status=200 ) + @check_precondition + def statistics(self, gid, sid, did, scid, tid, idx=None): + """ + Statistics + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + tid: Table Id + idx: Index Id + + Returns the statistics for a particular object if idx is specified + else return all indexes + """ + + if idx is not None: + # Individual index + + # Check if pgstattuple extension is already created? + # if created then only add extended stats + status, is_pgstattuple = self.conn.execute_scalar(""" + SELECT (count(extname) > 0) AS is_pgstattuple + FROM pg_extension + WHERE extname='pgstattuple' + """) + if not status: + return internal_server_error(errormsg=is_pgstattuple) + + if is_pgstattuple: + # Fetch index details only if extended stats available + SQL = render_template("/".join([self.template_path, + 'properties.sql']), + tid=tid, idx=idx, + datlastsysoid=self.datlastsysoid) + status, res = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + + data = dict(res['rows'][0]) + index = data['name'] + else: + index = None + + status, res = self.conn.execute_dict( + render_template( + "/".join([self.template_path, 'stats.sql']), + conn=self.conn, schema=self.schema, + index=index, idx=idx, is_pgstattuple=is_pgstattuple + ) + ) + + else: + status, res = self.conn.execute_dict( + render_template( + "/".join([self.template_path, 'coll_stats.sql']), + conn=self.conn, schema=self.schema, + table=self.table + ) + ) + + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + data=res, + status=200 + ) + IndexesView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/templates/index/js/index.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/templates/index/js/index.js index be3eca3..031225b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/templates/index/js/index.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/templates/index/js/index.js @@ -11,7 +11,8 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) { type: 'coll-index', sqlAlterHelp: 'sql-alterindex.html', sqlCreateHelp: 'sql-createindex.html', - columns: ['name', 'description'] + columns: ['name', 'description'], + hasStatistics: true }); }; @@ -199,6 +200,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) { label: '{{ _('Index') }}', hasSQL: true, hasDepends: true, + hasStatistics: true, Init: function() { /* Avoid mulitple registration of menus */ if (this.initialized) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..c00b647 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/9.1_plus/stats.sql @@ -0,0 +1,13 @@ +SELECT null_frac AS {{ conn|qtIdent(_('Null Fraction')) }}, + avg_width AS {{ conn|qtIdent(_('Average Width')) }}, + n_distinct AS {{ conn|qtIdent(_('Distinct Values')) }}, + most_common_vals AS {{ conn|qtIdent(_('Most Common Values')) }}, + most_common_freqs AS {{ conn|qtIdent(_('Most Common Frequencies')) }}, + histogram_bounds AS {{ conn|qtIdent(_('Histogram Bounds')) }}, + correlation AS {{ conn|qtIdent(_('Correlation')) }} +FROM + pg_stats +WHERE + schemaname = {{schema|qtLiteral}} + AND tablename = {{table|qtLiteral}} + AND attname = {{column|qtLiteral}}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/9.2_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/9.2_plus/stats.sql new file mode 100644 index 0000000..c00b647 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/9.2_plus/stats.sql @@ -0,0 +1,13 @@ +SELECT null_frac AS {{ conn|qtIdent(_('Null Fraction')) }}, + avg_width AS {{ conn|qtIdent(_('Average Width')) }}, + n_distinct AS {{ conn|qtIdent(_('Distinct Values')) }}, + most_common_vals AS {{ conn|qtIdent(_('Most Common Values')) }}, + most_common_freqs AS {{ conn|qtIdent(_('Most Common Frequencies')) }}, + histogram_bounds AS {{ conn|qtIdent(_('Histogram Bounds')) }}, + correlation AS {{ conn|qtIdent(_('Correlation')) }} +FROM + pg_stats +WHERE + schemaname = {{schema|qtLiteral}} + AND tablename = {{table|qtLiteral}} + AND attname = {{column|qtLiteral}}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..adb43e5 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/9.1_plus/stats.sql @@ -0,0 +1,27 @@ +SELECT idx_scan AS {{ conn|qtIdent(_('Index Scans')) }}, + idx_tup_read AS {{ conn|qtIdent(_('Index Tuples Read')) }}, + idx_tup_fetch AS {{ conn|qtIdent(_('Index Tuples Fetched')) }}, + idx_blks_read AS {{ conn|qtIdent(_('Index Blocks Read')) }}, + idx_blks_hit AS {{ conn|qtIdent(_('Index Blocks Hit')) }}, + pg_size_pretty(pg_relation_size({{ exid }}::OID)) AS {{ conn|qtIdent(_('Index Size')) }} +{#=== Extended stats ===#} +{% if is_pgstattuple %} + ,version AS {{ conn|qtIdent(_('Version')) }}, + tree_level AS {{ conn|qtIdent(_('Tree Level')) }}, + pg_size_pretty(index_size) AS {{ conn|qtIdent(_('Index Size')) }}, + root_block_no AS {{ conn|qtIdent(_('Root Block No')) }}, + internal_pages AS {{ conn|qtIdent(_('Internal Pages')) }}, + leaf_pages AS {{ conn|qtIdent(_('Leaf Pages')) }}, + empty_pages AS {{ conn|qtIdent(_('Empty Pages')) }}, + deleted_pages AS {{ conn|qtIdent(_('Deleted Pages')) }}, + avg_leaf_density AS {{ conn|qtIdent(_('Average Leaf Density')) }}, + leaf_fragmentation AS {{ conn|qtIdent(_('Leaf Fragmentation')) }} +FROM + pgstatindex('{{conn|qtIdent(schema)}}.{{conn|qtIdent(name)}}'), pg_stat_all_indexes stat +{% else %} +FROM + pg_stat_all_indexes stat +{% endif %} + JOIN pg_statio_all_indexes statio ON stat.indexrelid = statio.indexrelid + JOIN pg_class cl ON cl.oid=stat.indexrelid + WHERE stat.indexrelid = {{ exid }}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/9.2_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/9.2_plus/stats.sql new file mode 100644 index 0000000..adb43e5 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/9.2_plus/stats.sql @@ -0,0 +1,27 @@ +SELECT idx_scan AS {{ conn|qtIdent(_('Index Scans')) }}, + idx_tup_read AS {{ conn|qtIdent(_('Index Tuples Read')) }}, + idx_tup_fetch AS {{ conn|qtIdent(_('Index Tuples Fetched')) }}, + idx_blks_read AS {{ conn|qtIdent(_('Index Blocks Read')) }}, + idx_blks_hit AS {{ conn|qtIdent(_('Index Blocks Hit')) }}, + pg_size_pretty(pg_relation_size({{ exid }}::OID)) AS {{ conn|qtIdent(_('Index Size')) }} +{#=== Extended stats ===#} +{% if is_pgstattuple %} + ,version AS {{ conn|qtIdent(_('Version')) }}, + tree_level AS {{ conn|qtIdent(_('Tree Level')) }}, + pg_size_pretty(index_size) AS {{ conn|qtIdent(_('Index Size')) }}, + root_block_no AS {{ conn|qtIdent(_('Root Block No')) }}, + internal_pages AS {{ conn|qtIdent(_('Internal Pages')) }}, + leaf_pages AS {{ conn|qtIdent(_('Leaf Pages')) }}, + empty_pages AS {{ conn|qtIdent(_('Empty Pages')) }}, + deleted_pages AS {{ conn|qtIdent(_('Deleted Pages')) }}, + avg_leaf_density AS {{ conn|qtIdent(_('Average Leaf Density')) }}, + leaf_fragmentation AS {{ conn|qtIdent(_('Leaf Fragmentation')) }} +FROM + pgstatindex('{{conn|qtIdent(schema)}}.{{conn|qtIdent(name)}}'), pg_stat_all_indexes stat +{% else %} +FROM + pg_stat_all_indexes stat +{% endif %} + JOIN pg_statio_all_indexes statio ON stat.indexrelid = statio.indexrelid + JOIN pg_class cl ON cl.oid=stat.indexrelid + WHERE stat.indexrelid = {{ exid }}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index/sql/9.1_plus/coll_stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index/sql/9.1_plus/coll_stats.sql new file mode 100644 index 0000000..a469697 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index/sql/9.1_plus/coll_stats.sql @@ -0,0 +1,16 @@ +SELECT indexrelname AS {{ conn|qtIdent(_('Index Name')) }}, + idx_scan AS {{ conn|qtIdent(_('Index Scans')) }}, + idx_tup_read AS {{ conn|qtIdent(_('Index Tuples Read')) }}, + idx_tup_fetch AS {{ conn|qtIdent(_('Index Tuples Fetched')) }}, + pg_size_pretty(pg_relation_size(indexrelid)) AS {{ conn|qtIdent(_('Size')) }} +FROM + pg_stat_all_indexes stat + JOIN pg_class cls ON cls.oid=indexrelid + LEFT JOIN pg_depend dep ON (dep.classid = cls.tableoid AND dep.objid = cls.oid AND dep.refobjsubid = '0' + AND dep.refclassid=(SELECT oid FROM pg_class WHERE relname='pg_constraint')) + LEFT OUTER JOIN pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid) +WHERE + schemaname = '{{schema}}' + AND stat.relname = '{{table}}' + AND con.contype IS NULL +ORDER BY indexrelname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..9186f94 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index/sql/9.1_plus/stats.sql @@ -0,0 +1,27 @@ +SELECT idx_scan AS {{ conn|qtIdent(_('Index Scans')) }}, + idx_tup_read AS {{ conn|qtIdent(_('Index Tuples Read')) }}, + idx_tup_fetch AS {{ conn|qtIdent(_('Index Tuples Fetched')) }}, + idx_blks_read AS {{ conn|qtIdent(_('Index Blocks Read')) }}, + idx_blks_hit AS {{ conn|qtIdent(_('Index Blocks Hit')) }}, + pg_size_pretty(pg_relation_size({{ idx }}::OID)) AS {{ conn|qtIdent(_('Index Size')) }} +{#=== Extended stats ===#} +{% if is_pgstattuple %} + ,version AS {{ conn|qtIdent(_('Version')) }}, + tree_level AS {{ conn|qtIdent(_('Tree Level')) }}, + pg_size_pretty(index_size) AS {{ conn|qtIdent(_('Index Size')) }}, + root_block_no AS {{ conn|qtIdent(_('Root Block No')) }}, + internal_pages AS {{ conn|qtIdent(_('Internal Pages')) }}, + leaf_pages AS {{ conn|qtIdent(_('Leaf Pages')) }}, + empty_pages AS {{ conn|qtIdent(_('Empty Pages')) }}, + deleted_pages AS {{ conn|qtIdent(_('Deleted Pages')) }}, + avg_leaf_density AS {{ conn|qtIdent(_('Average Leaf Density')) }}, + leaf_fragmentation AS {{ conn|qtIdent(_('Leaf Fragmentation')) }} +FROM + pgstatindex('{{conn|qtIdent(schema)}}.{{conn|qtIdent(index)}}'), pg_stat_all_indexes stat +{% else %} +FROM + pg_stat_all_indexes stat +{% endif %} + JOIN pg_statio_all_indexes statio ON stat.indexrelid = statio.indexrelid + JOIN pg_class cl ON cl.oid=stat.indexrelid + WHERE stat.indexrelid = {{ idx }}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/stats.sql new file mode 100644 index 0000000..27dfbb0 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/stats.sql @@ -0,0 +1,27 @@ +SELECT idx_scan AS {{ conn|qtIdent(_('Index Scans')) }}, + idx_tup_read AS {{ conn|qtIdent(_('Index Tuples Read')) }}, + idx_tup_fetch AS {{ conn|qtIdent(_('Index Tuples Fetched')) }}, + idx_blks_read AS {{ conn|qtIdent(_('Index Blocks Read')) }}, + idx_blks_hit AS {{ conn|qtIdent(_('Index Blocks Hit')) }}, + pg_size_pretty(pg_relation_size({{ cid }}::OID)) AS {{ conn|qtIdent(_('Index Size')) }} +{#=== Extended stats ===#} +{% if is_pgstattuple %} + ,version AS {{ conn|qtIdent(_('Version')) }}, + tree_level AS {{ conn|qtIdent(_('Tree Level')) }}, + pg_size_pretty(index_size) AS {{ conn|qtIdent(_('Index Size')) }}, + root_block_no AS {{ conn|qtIdent(_('Root Block No')) }}, + internal_pages AS {{ conn|qtIdent(_('Internal Pages')) }}, + leaf_pages AS {{ conn|qtIdent(_('Leaf Pages')) }}, + empty_pages AS {{ conn|qtIdent(_('Empty Pages')) }}, + deleted_pages AS {{ conn|qtIdent(_('Deleted Pages')) }}, + avg_leaf_density AS {{ conn|qtIdent(_('Average Leaf Density')) }}, + leaf_fragmentation AS {{ conn|qtIdent(_('Leaf Fragmentation')) }} +FROM + pgstatindex('{{conn|qtIdent(schema)}}.{{conn|qtIdent(name)}}'), pg_stat_all_indexes stat +{% else %} +FROM + pg_stat_all_indexes stat +{% endif %} + JOIN pg_statio_all_indexes statio ON stat.indexrelid = statio.indexrelid + JOIN pg_class cl ON cl.oid=stat.indexrelid + WHERE stat.indexrelid = {{ cid }}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/js/table.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/js/table.js index c62aa0d..4ea249d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/js/table.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/js/table.js @@ -12,7 +12,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { node: 'table', label: '{{ _('Tables') }}', type: 'coll-table', - columns: ['name', 'relowner', 'description'] + columns: ['name', 'relowner', 'description'], + hasStatistics: true }); }; @@ -23,6 +24,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { collection_type: 'coll-table', hasSQL: true, hasDepends: true, + hasStatistics: true, sqlAlterHelp: 'sql-altertable.html', sqlCreateHelp: 'sql-createtable.html', dialogHelp: '{{ url_for('help.static', filename='table_dialog.html') }}', diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/coll_table_stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/coll_table_stats.sql new file mode 100644 index 0000000..5aa9697 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/coll_table_stats.sql @@ -0,0 +1,28 @@ +SELECT st.relname AS {{ conn|qtIdent(_('Table Name')) }}, + n_tup_ins AS {{ conn|qtIdent(_('Tuples inserted')) }}, + n_tup_upd AS {{ conn|qtIdent(_('Tuples updated')) }}, + n_tup_del AS {{ conn|qtIdent(_('Tuples deleted')) }}, + n_tup_hot_upd AS {{ conn|qtIdent(_('Tuples HOT updated')) }}, + n_live_tup AS {{ conn|qtIdent(_('Live tuples')) }}, + n_dead_tup AS {{ conn|qtIdent(_('Dead tuples')) }}, + last_vacuum AS {{ conn|qtIdent(_('Last vacuum')) }}, + last_autovacuum AS {{ conn|qtIdent(_('Last autovacuum')) }}, + last_analyze AS {{ conn|qtIdent(_('Last analyze')) }}, + last_autoanalyze AS {{ conn|qtIdent(_('Last autoanalyze')) }}, + vacuum_count AS {{ conn|qtIdent(_('Vacuum counter')) }}, + autovacuum_count AS {{ conn|qtIdent(_('Autovacuum counter')) }}, + analyze_count AS {{ conn|qtIdent(_('Analyze counter')) }}, + autoanalyze_count AS {{ conn|qtIdent(_('Autoanalyze counter')) }}, + pg_size_pretty(pg_relation_size(st.relid) + + CASE WHEN cl.reltoastrelid = 0 THEN 0 ELSE pg_relation_size(cl.reltoastrelid) + + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) + FROM pg_index WHERE indrelid=cl.reltoastrelid)::int8, 0) END + + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) + FROM pg_index WHERE indrelid=st.relid)::int8, 0)) AS {{ conn|qtIdent(_('Size')) }} +FROM + pg_stat_all_tables st +JOIN + pg_class cl on cl.oid=st.relid +WHERE + schemaname = {{schema_name|qtLiteral}} +ORDER BY st.relname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/get_schema.sql new file mode 100644 index 0000000..3c5187d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/get_schema.sql @@ -0,0 +1 @@ +SELECT nsp.nspname FROM pg_namespace nsp WHERE nsp.oid = {{ scid|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/get_table.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/get_table.sql new file mode 100644 index 0000000..89a15c4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/get_table.sql @@ -0,0 +1,7 @@ +SELECT rel.relname AS name +FROM + pg_class rel +WHERE + rel.relkind IN ('r','s','t') + AND rel.relnamespace = {{ scid }}::oid + AND rel.oid = {{ tid }}::oid; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/stats.sql new file mode 100644 index 0000000..824f701 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/stats.sql @@ -0,0 +1,56 @@ +SELECT seq_scan AS {{ conn|qtIdent(_('Sequential Scans')) }}, + seq_tup_read AS {{ conn|qtIdent(_('Sequential Tuples Read')) }}, + idx_scan AS {{ conn|qtIdent(_('Index Scans')) }}, + idx_tup_fetch AS {{ conn|qtIdent(_('Index Tuples Fetched')) }}, + n_tup_ins AS {{ conn|qtIdent(_('Tuples Inserted')) }}, + n_tup_upd AS {{ conn|qtIdent(_('Tuples Updated')) }}, + n_tup_del AS {{ conn|qtIdent(_('Tuples Deleted')) }}, + n_tup_hot_upd AS {{ conn|qtIdent(_('Tuples HOT Updated')) }}, + n_live_tup AS {{ conn|qtIdent(_('Live Tuples')) }}, + n_dead_tup AS {{ conn|qtIdent(_('Dead Tuples')) }}, + heap_blks_read AS {{ conn|qtIdent(_('Heap Blocks Read')) }}, + heap_blks_hit AS {{ conn|qtIdent(_('Heap Blocks Hit')) }}, + idx_blks_read AS {{ conn|qtIdent(_('Index Blocks Read')) }}, + idx_blks_hit AS {{ conn|qtIdent(_('Index Blocks Hit')) }}, + toast_blks_read AS {{ conn|qtIdent(_('Toast Blocks Read')) }}, + toast_blks_hit AS {{ conn|qtIdent(_('Toast Blocks Hit')) }}, + tidx_blks_read AS {{ conn|qtIdent(_('Toast Index Blocks Read')) }}, + tidx_blks_hit AS {{ conn|qtIdent(_('Toast Index Blocks Hit')) }}, + last_vacuum AS {{ conn|qtIdent(_('Last Vacuum')) }}, + last_autovacuum AS {{ conn|qtIdent(_('Last Autovacuum')) }}, + last_analyze AS {{ conn|qtIdent(_('Last Analyze')) }}, + last_autoanalyze AS {{ conn|qtIdent(_('Last Autoanalyze')) }}, + vacuum_count AS {{ conn|qtIdent(_('Vacuum counter')) }}, + autovacuum_count AS {{ conn|qtIdent(_('Autovacuum counter')) }}, + analyze_count AS {{ conn|qtIdent(_('Analyze counter')) }}, + autoanalyze_count AS {{ conn|qtIdent(_('Autoanalyze counter')) }}, + pg_size_pretty(pg_relation_size(stat.relid)) AS {{ conn|qtIdent(_('Table Size')) }}, + CASE WHEN cl.reltoastrelid = 0 THEN NULL ELSE pg_size_pretty(pg_relation_size(cl.reltoastrelid) + + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) + FROM pg_index WHERE indrelid=cl.reltoastrelid)::int8, 0)) + END AS {{ conn|qtIdent(_('Toast Table Size')) }}, + pg_size_pretty(COALESCE((SELECT SUM(pg_relation_size(indexrelid)) + FROM pg_index WHERE indrelid=stat.relid)::int8, 0)) + AS {{ conn|qtIdent(_('Indexes Size')) }} +{% if is_pgstattuple %} +{#== EXTENDED STATS ==#} + ,tuple_count AS {{ conn|qtIdent(_('Tuple Count')) }}, + pg_size_pretty(tuple_len) AS {{ conn|qtIdent(_('Tuple Length')) }}, + tuple_percent AS {{ conn|qtIdent(_('Tuple Percent')) }}, + dead_tuple_count AS {{ conn|qtIdent(_('Dead Tuple Count')) }}, + pg_size_pretty(dead_tuple_len) AS {{ conn|qtIdent(_('Dead Tuple Length')) }}, + dead_tuple_percent AS {{ conn|qtIdent(_('Dead Tuple Percent')) }}, + pg_size_pretty(free_space) AS {{ conn|qtIdent(_('Free Space')) }}, + free_percent AS {{ conn|qtIdent(_('Free Percent')) }} +FROM + pgstattuple('{{schema_name}}.{{table_name}}'), pg_stat_all_tables stat +{% else %} +FROM + pg_stat_all_tables stat +{% endif %} +JOIN + pg_statio_all_tables statio ON stat.relid = statio.relid +JOIN + pg_class cl ON cl.oid=stat.relid +WHERE + stat.relid = {{ tid }}::oid diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/coll_table_stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/coll_table_stats.sql new file mode 100644 index 0000000..5aa9697 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/coll_table_stats.sql @@ -0,0 +1,28 @@ +SELECT st.relname AS {{ conn|qtIdent(_('Table Name')) }}, + n_tup_ins AS {{ conn|qtIdent(_('Tuples inserted')) }}, + n_tup_upd AS {{ conn|qtIdent(_('Tuples updated')) }}, + n_tup_del AS {{ conn|qtIdent(_('Tuples deleted')) }}, + n_tup_hot_upd AS {{ conn|qtIdent(_('Tuples HOT updated')) }}, + n_live_tup AS {{ conn|qtIdent(_('Live tuples')) }}, + n_dead_tup AS {{ conn|qtIdent(_('Dead tuples')) }}, + last_vacuum AS {{ conn|qtIdent(_('Last vacuum')) }}, + last_autovacuum AS {{ conn|qtIdent(_('Last autovacuum')) }}, + last_analyze AS {{ conn|qtIdent(_('Last analyze')) }}, + last_autoanalyze AS {{ conn|qtIdent(_('Last autoanalyze')) }}, + vacuum_count AS {{ conn|qtIdent(_('Vacuum counter')) }}, + autovacuum_count AS {{ conn|qtIdent(_('Autovacuum counter')) }}, + analyze_count AS {{ conn|qtIdent(_('Analyze counter')) }}, + autoanalyze_count AS {{ conn|qtIdent(_('Autoanalyze counter')) }}, + pg_size_pretty(pg_relation_size(st.relid) + + CASE WHEN cl.reltoastrelid = 0 THEN 0 ELSE pg_relation_size(cl.reltoastrelid) + + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) + FROM pg_index WHERE indrelid=cl.reltoastrelid)::int8, 0) END + + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) + FROM pg_index WHERE indrelid=st.relid)::int8, 0)) AS {{ conn|qtIdent(_('Size')) }} +FROM + pg_stat_all_tables st +JOIN + pg_class cl on cl.oid=st.relid +WHERE + schemaname = {{schema_name|qtLiteral}} +ORDER BY st.relname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/get_schema.sql new file mode 100644 index 0000000..3c5187d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/get_schema.sql @@ -0,0 +1 @@ +SELECT nsp.nspname FROM pg_namespace nsp WHERE nsp.oid = {{ scid|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/get_table.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/get_table.sql new file mode 100644 index 0000000..89a15c4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/get_table.sql @@ -0,0 +1,7 @@ +SELECT rel.relname AS name +FROM + pg_class rel +WHERE + rel.relkind IN ('r','s','t') + AND rel.relnamespace = {{ scid }}::oid + AND rel.oid = {{ tid }}::oid; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/stats.sql new file mode 100644 index 0000000..824f701 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.5_plus/stats.sql @@ -0,0 +1,56 @@ +SELECT seq_scan AS {{ conn|qtIdent(_('Sequential Scans')) }}, + seq_tup_read AS {{ conn|qtIdent(_('Sequential Tuples Read')) }}, + idx_scan AS {{ conn|qtIdent(_('Index Scans')) }}, + idx_tup_fetch AS {{ conn|qtIdent(_('Index Tuples Fetched')) }}, + n_tup_ins AS {{ conn|qtIdent(_('Tuples Inserted')) }}, + n_tup_upd AS {{ conn|qtIdent(_('Tuples Updated')) }}, + n_tup_del AS {{ conn|qtIdent(_('Tuples Deleted')) }}, + n_tup_hot_upd AS {{ conn|qtIdent(_('Tuples HOT Updated')) }}, + n_live_tup AS {{ conn|qtIdent(_('Live Tuples')) }}, + n_dead_tup AS {{ conn|qtIdent(_('Dead Tuples')) }}, + heap_blks_read AS {{ conn|qtIdent(_('Heap Blocks Read')) }}, + heap_blks_hit AS {{ conn|qtIdent(_('Heap Blocks Hit')) }}, + idx_blks_read AS {{ conn|qtIdent(_('Index Blocks Read')) }}, + idx_blks_hit AS {{ conn|qtIdent(_('Index Blocks Hit')) }}, + toast_blks_read AS {{ conn|qtIdent(_('Toast Blocks Read')) }}, + toast_blks_hit AS {{ conn|qtIdent(_('Toast Blocks Hit')) }}, + tidx_blks_read AS {{ conn|qtIdent(_('Toast Index Blocks Read')) }}, + tidx_blks_hit AS {{ conn|qtIdent(_('Toast Index Blocks Hit')) }}, + last_vacuum AS {{ conn|qtIdent(_('Last Vacuum')) }}, + last_autovacuum AS {{ conn|qtIdent(_('Last Autovacuum')) }}, + last_analyze AS {{ conn|qtIdent(_('Last Analyze')) }}, + last_autoanalyze AS {{ conn|qtIdent(_('Last Autoanalyze')) }}, + vacuum_count AS {{ conn|qtIdent(_('Vacuum counter')) }}, + autovacuum_count AS {{ conn|qtIdent(_('Autovacuum counter')) }}, + analyze_count AS {{ conn|qtIdent(_('Analyze counter')) }}, + autoanalyze_count AS {{ conn|qtIdent(_('Autoanalyze counter')) }}, + pg_size_pretty(pg_relation_size(stat.relid)) AS {{ conn|qtIdent(_('Table Size')) }}, + CASE WHEN cl.reltoastrelid = 0 THEN NULL ELSE pg_size_pretty(pg_relation_size(cl.reltoastrelid) + + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) + FROM pg_index WHERE indrelid=cl.reltoastrelid)::int8, 0)) + END AS {{ conn|qtIdent(_('Toast Table Size')) }}, + pg_size_pretty(COALESCE((SELECT SUM(pg_relation_size(indexrelid)) + FROM pg_index WHERE indrelid=stat.relid)::int8, 0)) + AS {{ conn|qtIdent(_('Indexes Size')) }} +{% if is_pgstattuple %} +{#== EXTENDED STATS ==#} + ,tuple_count AS {{ conn|qtIdent(_('Tuple Count')) }}, + pg_size_pretty(tuple_len) AS {{ conn|qtIdent(_('Tuple Length')) }}, + tuple_percent AS {{ conn|qtIdent(_('Tuple Percent')) }}, + dead_tuple_count AS {{ conn|qtIdent(_('Dead Tuple Count')) }}, + pg_size_pretty(dead_tuple_len) AS {{ conn|qtIdent(_('Dead Tuple Length')) }}, + dead_tuple_percent AS {{ conn|qtIdent(_('Dead Tuple Percent')) }}, + pg_size_pretty(free_space) AS {{ conn|qtIdent(_('Free Space')) }}, + free_percent AS {{ conn|qtIdent(_('Free Percent')) }} +FROM + pgstattuple('{{schema_name}}.{{table_name}}'), pg_stat_all_tables stat +{% else %} +FROM + pg_stat_all_tables stat +{% endif %} +JOIN + pg_statio_all_tables statio ON stat.relid = statio.relid +JOIN + pg_class cl ON cl.oid=stat.relid +WHERE + stat.relid = {{ tid }}::oid