From 966279c1b3cc9137ed6bb7ba21e76d0981178b3c Mon Sep 17 00:00:00 2001 From: Joao De Almeida Pereira Date: Thu, 26 Apr 2018 17:05:56 +0530 Subject: [PATCH] Fixed issue where icon for Partitioned tables was the same as Non Partitioned tables for GreenPlum database. Fixes #3308 --- docs/en_US/release_notes_3_1.rst | 3 +- .../databases/schemas/tables/__init__.py | 34 ++---- .../schemas/tables/base_partition_table.py | 23 ++++ .../schemas/tables/partitions/__init__.py | 2 +- .../table/sql/gpdb_5.0_plus/nodes.sql | 3 +- .../tables/tests/test_base_partition_table.py | 107 ++++++++++++++++++ .../servers/databases/schemas/tables/utils.py | 13 +-- 7 files changed, 152 insertions(+), 33 deletions(-) create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/base_partition_table.py create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/tests/test_base_partition_table.py diff --git a/docs/en_US/release_notes_3_1.rst b/docs/en_US/release_notes_3_1.rst index 7b410b1d5..b9df49bce 100644 --- a/docs/en_US/release_notes_3_1.rst +++ b/docs/en_US/release_notes_3_1.rst @@ -17,4 +17,5 @@ Bug fixes | `Bug #3179 `_ - Fix an error generating SQL for trigger functions | `Bug #3257 `_ - Catch errors when trying to EXPLAIN an invalid query | `Bug #3290 `_ - Close button added to the alertify message box, which pops up in case of backend error -| `Bug #3306 `_ - Fixed display SQL of table with index for GreenPlum database \ No newline at end of file +| `Bug #3306 `_ - Fixed display SQL of table with index for GreenPlum database +| `Bug #3308 `_ - Fixed issue where icon for Partitioned tables was the same as Non Partitioned tables for GreenPlum database \ 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 d49ca20e1..a4c229a1e 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 @@ -303,21 +303,17 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings): if len(rset['rows']) == 0: return gone(gettext("Could not find the table.")) - if 'is_partitioned' in rset['rows'][0] and \ - rset['rows'][0]['is_partitioned']: - icon = "icon-partition" - else: - icon = "icon-table" + table_information = rset['rows'][0] + icon = self.get_icon_css_class(table_information) res = self.blueprint.generate_browser_node( - rset['rows'][0]['oid'], + table_information['oid'], scid, - rset['rows'][0]['name'], + table_information['name'], icon=icon, - tigger_count=rset['rows'][0]['triggercount'], - has_enable_triggers=rset['rows'][0]['has_enable_triggers'], - is_partitioned=rset['rows'][0]['is_partitioned'] if - 'is_partitioned' in rset['rows'][0] else False + tigger_count=table_information['triggercount'], + has_enable_triggers=table_information['has_enable_triggers'], + is_partitioned=self.is_table_partitioned(table_information) ) return make_json_response( @@ -350,10 +346,7 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings): return internal_server_error(errormsg=rset) for row in rset['rows']: - if 'is_partitioned' in row and row['is_partitioned']: - icon = "icon-partition" - else: - icon = "icon-table" + icon = self.get_icon_css_class(row) res.append( self.blueprint.generate_browser_node( @@ -363,8 +356,7 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings): icon=icon, 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=self.is_table_partitioned(row), rows_cnt=0 )) @@ -968,13 +960,11 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings): try: partitions_sql = '' - partitioned = False - if 'is_partitioned' in data and data['is_partitioned']: + if self.is_table_partitioned(data): data['relkind'] = 'p' # create partition scheme data['partition_scheme'] = self.get_partition_scheme(data) partitions_sql = self.get_partitions_sql(data) - partitioned = True SQL = render_template( "/".join([self.table_template_path, 'create.sql']), @@ -1021,8 +1011,8 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings): tid, scid, data['name'], - icon="icon-partition" if partitioned else "icon-table", - is_partitioned=partitioned + icon=self.get_icon_css_class(data), + is_partitioned=self.is_table_partitioned(data) ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/base_partition_table.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/base_partition_table.py new file mode 100644 index 000000000..fd81f6da9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/base_partition_table.py @@ -0,0 +1,23 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2018, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + + +class BasePartitionTable: + def is_table_partitioned(self, table_info): + if ( + getattr(self, 'node_type', '') == 'partition' or + ('is_partitioned' in table_info and table_info['is_partitioned']) + ): + return True + return False + + def get_icon_css_class(self, table_info): + if self.is_table_partitioned(table_info): + return 'icon-partition' + return 'icon-table' diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py index df1957332..b1031d8b6 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py @@ -308,7 +308,7 @@ class PartitionsView(BaseTableView, DataTypeReader, VacuumSettings): row['oid'], tid, row['name'], - icon="icon-partition", + icon=self.get_icon_css_class({}), tigger_count=row['triggercount'], has_enable_triggers=row['has_enable_triggers'], is_partitioned=row['is_partitioned'], diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/gpdb_5.0_plus/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/gpdb_5.0_plus/nodes.sql index 3e877bfce..8c1e5878c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/gpdb_5.0_plus/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/gpdb_5.0_plus/nodes.sql @@ -1,6 +1,7 @@ SELECT rel.oid, rel.relname AS name, (SELECT count(*) FROM pg_trigger WHERE tgrelid=rel.oid) AS triggercount, - (SELECT count(*) FROM pg_trigger WHERE tgrelid=rel.oid AND tgenabled = 'O') AS has_enable_triggers + (SELECT count(*) FROM pg_trigger WHERE tgrelid=rel.oid AND tgenabled = 'O') AS has_enable_triggers, + (CASE WHEN (SELECT count(*) from pg_partition where parrelid = rel.oid) > 0 THEN true ELSE false END) AS is_partitioned FROM pg_class rel WHERE rel.relkind IN ('r','s','t') AND rel.relnamespace = {{ scid }}::oid AND rel.relname NOT IN (SELECT partitiontablename FROM pg_partitions) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/tests/test_base_partition_table.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/tests/test_base_partition_table.py new file mode 100644 index 000000000..38c040f01 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/tests/test_base_partition_table.py @@ -0,0 +1,107 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2018, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## +from pgadmin.browser.server_groups.servers.databases.schemas\ + .tables.base_partition_table import BasePartitionTable +from pgadmin.utils.route import BaseTestGenerator + + +class TestBasePartitionTable(BaseTestGenerator): + scenarios = [ + ('#is_table_partitioned when table information does not ' + 'have partition information, ' + 'it returns false', + dict( + test='is_table_partitioned', + input_parameters=dict(), + expected_return=False + )), + ('#is_table_partitioned when table information ' + 'has partition information and table is partitioned, ' + 'it returns true', + dict( + test='is_table_partitioned', + input_parameters=dict( + is_partitioned=True + ), + expected_return=True + )), + ('#is_table_partitioned when table information ' + 'has partition information and table is not partitioned, ' + 'it returns false', + dict( + test='is_table_partitioned', + input_parameters=dict( + is_partitioned=False + ), + expected_return=False + )), + ('#is_table_partitioned when node_type is present ' + 'and is partition, ' + 'it returns true', + dict( + test='is_table_partitioned', + input_parameters=dict( + is_partitioned=False + ), + node_type='partition', + expected_return=True + )), + ('#is_table_partitioned when node_type is present ' + 'and is not partition ' + 'and table is not partitioned ' + 'it returns true', + dict( + test='is_table_partitioned', + input_parameters=dict( + is_partitioned=False + ), + node_type='table', + expected_return=False + )), + + + ('#get_icon_css_class when table is partitioned ' + 'it returns icon-partition class', + dict( + test='get_icon_css_class', + input_parameters=dict( + is_partitioned=True + ), + expected_return='icon-partition' + )), + ('#get_icon_css_class when table is not partitioned ' + 'it returns icon-table class', + dict( + test='get_icon_css_class', + input_parameters=dict( + is_partitioned=False + ), + expected_return='icon-table' + )) + ] + + def runTest(self): + if self.test == 'is_table_partitioned': + self.__test_is_table_partitioned() + elif self.test == 'get_icon_css_class': + self.__test_get_icon_css_class() + + def __test_is_table_partitioned(self): + subject = BasePartitionTable() + if hasattr(self, 'node_type'): + subject.node_type = self.node_type + + self.assertEqual(subject.is_table_partitioned(self.input_parameters), + self.expected_return) + + def __test_get_icon_css_class(self): + subject = BasePartitionTable() + + self.assertEqual(subject.get_icon_css_class(self.input_parameters), + self.expected_return) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py index 3dc07493a..9ef065419 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py @@ -14,6 +14,9 @@ from functools import wraps import simplejson as json from flask import render_template, jsonify, request from flask_babelex import gettext + +from pgadmin.browser.server_groups.servers.databases.schemas\ + .tables.base_partition_table import BasePartitionTable from pgadmin.utils.ajax import make_json_response, internal_server_error, \ make_response as ajax_response from pgadmin.browser.server_groups.servers.databases.schemas.utils \ @@ -27,7 +30,7 @@ from pgadmin.utils.driver import get_driver from config import PG_DEFAULT_DRIVER -class BaseTableView(PGChildNodeView): +class BaseTableView(PGChildNodeView, BasePartitionTable): """ This class is base class for tables and partitioned tables. @@ -2067,13 +2070,7 @@ class BaseTableView(PGChildNodeView): partitions_oid['created'] = created partitions_oid['attached'] = attached - if self.node_type == 'partition': - icon = "icon-partition" - elif 'is_partitioned' in res['rows'][0] and \ - res['rows'][0]['is_partitioned']: - icon = "icon-partition" - else: - icon = "icon-table" + icon = self.get_icon_css_class(res['rows'][0]) if 'relkind' in res['rows'][0] and \ res['rows'][0]['relkind'] == 'p':