Hi, Please find the attached patch for RM #2846 : Add a context menu option to manually (re)count rows in tables, including those with >2K rows
Thanks, Khushboo
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 1b24ee5..aa2adc9 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 @@ -242,7 +242,8 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings): 'select_sql': [{'get': 'select_sql'}], 'insert_sql': [{'get': 'insert_sql'}], 'update_sql': [{'get': 'update_sql'}], - 'delete_sql': [{'get': 'delete_sql'}] + 'delete_sql': [{'get': 'delete_sql'}], + 'count_rows': [{'get': 'count_rows'}] }) @BaseTableView.check_precondition @@ -346,7 +347,8 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings): icon="icon-partition" if 'is_partitioned' in row and row['is_partitioned'] else "icon-table", tigger_count=row['triggercount'], has_enable_triggers=row['has_enable_triggers'], - is_partitioned=row['is_partitioned'] if 'is_partitioned' in row else False + is_partitioned=row['is_partitioned'] if 'is_partitioned' in row else False, + rows_cnt=0 )) return make_json_response( @@ -1461,4 +1463,39 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings): """ return BaseTableView.get_table_statistics(self, scid, tid) + @BaseTableView.check_precondition + def count_rows(self, gid, sid, did, scid, tid): + """ + Count the rows of a table. + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + tid: Table Id + + Returns the total rows of a table. + """ + data = {} + data['schema'], data['name'] = \ + super(TableView, self).get_schema_and_table_name(tid) + + SQL = render_template( + "/".join( + [self.table_template_path, 'get_table_row_count.sql'] + ), data=data + ) + + status, count = self.conn.execute_scalar(SQL) + + if not status: + return internal_server_error(errormsg=count) + + return make_json_response( + status=200, + info=gettext("Table rows counted"), + data={'total_rows': count} + ) + + TableView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js index 90217e0..359a356 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js @@ -90,6 +90,11 @@ define('pgadmin.node.table', [ applies: ['object', 'context'], callback: 'reset_table_stats', category: 'Reset', priority: 4, label: gettext('Reset Statistics'), icon: 'fa fa-bar-chart', enable : 'canCreate' + },{ + name: 'count_table_rows', node: 'table', module: this, + applies: ['object', 'context'], callback: 'count_table_rows', + category: 'Count', priority: 2, label: gettext('Count'), + enable: true } ]); pgBrowser.Events.on( @@ -206,8 +211,8 @@ define('pgadmin.node.table', [ } }, function() {} ); - }, - reset_table_stats: function(args) { + }, + reset_table_stats: function(args) { var input = args || {}, obj = this, t = pgBrowser.tree, @@ -255,7 +260,41 @@ define('pgadmin.node.table', [ }, function() {} ); - } + }, + count_table_rows: function(args) { + 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; + + // Fetch the total rows of a table + $.ajax({ + url: obj.generate_url(i, 'count_rows' , d, true), + type:'GET', + success: function(res) { + alertify.success(res.info); + d.rows_cnt = res.data.total_rows; + t.unload(i); + t.setInode(i); + t.deselect(i); + setTimeout(function() { + t.select(i); + }, 10); + }, + error: function(xhr, status, error) { + try { + var err = $.parseJSON(xhr.responseText); + if (err.success == 0) { + alertify.error(err.errormsg); + } + } catch (e) {} + t.unload(i); + } + }); + } }, model: pgBrowser.Node.Model.extend({ defaults: { @@ -781,7 +820,24 @@ define('pgadmin.node.table', [ },{ id: 'rows_cnt', label: gettext('Rows (counted)'), cell: 'string', type: 'text', mode: ['properties'], group: gettext('Advanced'), - disabled: 'inSchema' + disabled: 'inSchema', control: Backform.InputControl.extend({ + formatter: { + fromRaw: function (rawData, model) { + var t = pgAdmin.Browser.tree, + i = t.selected(), + d = i && i.length == 1 ? t.itemData(i) : undefined; + + // Return the actual rows count if the selected node has already counted. + if(d && d.rows_cnt && parseInt(d.rows_cnt, 10) > 0) + return d.rows_cnt; + else + return rawData; + }, + toRaw: function (formattedData, model) { + return formattedData; + } + } + }) },{ id: 'relhassubclass', label: gettext('Inherits tables?'), cell: 'switch', type: 'switch', mode: ['properties'], group: gettext('Advanced'), diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js index fefe9cc..9a5b894 100644 --- a/web/pgadmin/browser/static/js/node.js +++ b/web/pgadmin/browser/static/js/node.js @@ -453,7 +453,7 @@ define( * * args must be a object containing: * action - create/edit/properties - * item - The properties of the item (tree ndoe item) + * item - The properties of the item (tree node item) * * NOTE: * if item is not provided, the action will be done on the