From ed3cb7df417b3e0b4a1dc3da8d4224a09727412e Mon Sep 17 00:00:00 2001 From: Akshay Joshi Date: Mon, 10 Jul 2017 14:16:30 +0100 Subject: [PATCH] Handle partitioned tables created "OF TYPE". Fixes #2545 --- .../databases/schemas/tables/__init__.py | 11 +++++- .../tables/static/js/partition.utils.js | 18 ++++++++- .../schemas/tables/static/js/table.js | 39 ++++++++++++------- .../table/sql/10_plus/properties.sql | 3 +- .../table/sql/9.1_plus/properties.sql | 3 +- .../templates/table/sql/default/create.sql | 3 +- 6 files changed, 56 insertions(+), 21 deletions(-) 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 17d97075a..cd61906e2 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 @@ -661,9 +661,18 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings): if not status: return internal_server_error(errormsg=res) for row in rset['rows']: + # Get columns for all 'OF TYPES'. + SQL = render_template("/".join([self.table_template_path, + 'get_columns_for_table.sql']), + tid=row['oid']) + + status, type_cols = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=type_cols) + res.append( {'label': row['typname'], 'value': row['typname'], - 'tid': row['oid'] + 'tid': row['oid'], 'oftype_columns': type_cols['rows'] } ) return make_json_response( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/partition.utils.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/partition.utils.js index 6fe46bae2..a1b7a9aae 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/partition.utils.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/partition.utils.js @@ -116,7 +116,9 @@ function(gettext, $, _, pgBrowser, Backform, Backgrid) { custom_options: function() { // We will add all the columns entered by user in table model var columns = this.model.top.get('columns'), - added_columns_from_tables = []; + typename = this.model.top.get('typname'), + of_types_tables = this.model.top.of_types_tables, + added_columns_from_tables = []; if (columns.length > 0) { _.each(columns.models, function(m) { @@ -127,7 +129,21 @@ function(gettext, $, _, pgBrowser, Backform, Backgrid) { ); } }); + } else if (!_.isUndefined(typename) && !_.isNull(typename) + && !_.isUndefined(of_types_tables) && of_types_tables.length > 0) { + // Iterate through all the of_type tables + _.each(of_types_tables, function(type) { + if (type.label == typename) { + // Iterate all the columns of selected "OF TYPE". + _.each(type.oftype_columns, function(col) { + added_columns_from_tables.push( + {label: col.name, value: col.name, image:'icon-column'} + ); + }); + } + }); } + // Set the values in to options so that user can select this.column.set('options', added_columns_from_tables); }, 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 7560be406..077f4d524 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 @@ -708,7 +708,7 @@ define('pgadmin.node.table', [ id: 'typname', label: gettext('Of type'), type: 'text', control: 'node-ajax-options', mode: ['properties', 'create', 'edit'], disabled: 'checkOfType', url: 'get_oftype', group: gettext('Advanced'), - deps: ['coll_inherits', 'is_partitioned'], transform: function(data, cell) { + deps: ['coll_inherits'], transform: function(data, cell) { var control = cell || this, m = control.model; m.of_types_tables = data; @@ -854,7 +854,7 @@ define('pgadmin.node.table', [ subnode: Backform.PartitionKeyModel, editable: true, type: 'collection', group: 'partition', mode: ['create'], - deps: ['is_partitioned', 'partition_type'], + deps: ['is_partitioned', 'partition_type', 'typname'], canEdit: false, canDelete: true, control: 'sub-node-collection', canAdd: function(m) { @@ -863,16 +863,33 @@ define('pgadmin.node.table', [ return false; }, canAddRow: function(m) { - var columns = m.get('columns'); - var max_row_count = 1000; + var columns = m.get('columns'), + typename = m.get('typname'), + columns_exist= false; + var max_row_count = 1000; if (m.get('partition_type') && m.get('partition_type') == 'list') max_row_count = 1; + /* If columns are not specified by the user then it may be + * possible that he/she selected 'OF TYPE', so we should check + * for that as well. + */ + if (columns.length <= 0 && !_.isUndefined(typename) + && !_.isNull(typename) && m.of_types_tables.length > 0){ + _.each(m.of_types_tables, function(data) { + if (data.label == typename && data.oftype_columns.length > 0){ + columns_exist = true; + } + }); + } else if (columns.length > 0) { + columns_exist = _.some(columns.pluck('name')); + } + return (m.get('partition_keys') && - m.get('partition_keys').length < max_row_count && - _.some(columns.pluck('name')) + m.get('partition_keys').length < max_row_count && columns_exist ); + }, visible: function(m) { if(!_.isUndefined(m.node_info) && !_.isUndefined(m.node_info.server) @@ -938,7 +955,7 @@ define('pgadmin.node.table', [ subnode: Backform.PartitionsModel, editable: true, type: 'collection', group: 'partition', mode: ['edit', 'create'], - deps: ['is_partitioned', 'partition_type'], + deps: ['is_partitioned', 'partition_type', 'typname'], canEdit: false, canDelete: true, customDeleteTitle: gettext('Detach Partition'), customDeleteMsg: gettext('Are you sure you wish to detach this partition?'), @@ -1181,14 +1198,6 @@ define('pgadmin.node.table', [ }, // We will disable it if Inheritance is defined checkOfType: function(m) { - // Disabled if it is partitioned table - if (m.get('is_partitioned')) { - setTimeout( function() { - m.set('typname', undefined); - }, 10); - return true; - } - //coll_inherits || typname if(!m.inSchemaWithModelCheck.apply(this, [m]) && (_.isUndefined(m.get('coll_inherits')) || diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/properties.sql index 1d589df62..6d98b9d79 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/properties.sql @@ -51,7 +51,8 @@ SELECT rel.oid, rel.relname AS name, rel.reltablespace AS spcoid,rel.relacl AS r substring(array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age, array_to_string(rel.reloptions, ',') AS table_vacuum_settings_str, array_to_string(tst.reloptions, ',') AS toast_table_vacuum_settings_str, - rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, typ.typname, + rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, + (select quote_ident(nspname) FROM pg_namespace WHERE oid = {{scid}}::oid )||'.'||quote_ident(typ.typname) AS typname, (CASE WHEN rel.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable, -- Added for pgAdmin4 (CASE WHEN (substring(array_to_string(rel.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean THEN true ELSE false END) AS autovacuum_custom, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/properties.sql index 9bfb84a0a..cb23dce9d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/9.1_plus/properties.sql @@ -50,7 +50,8 @@ SELECT rel.oid, rel.relname AS name, rel.reltablespace AS spcoid,rel.relacl AS r substring(array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age, array_to_string(rel.reloptions, ',') AS table_vacuum_settings_str, array_to_string(tst.reloptions, ',') AS toast_table_vacuum_settings_str, - rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, typ.typname, + rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, + (select quote_ident(nspname) FROM pg_namespace WHERE oid = {{scid}}::oid )||'.'||quote_ident(typ.typname) AS typname, (CASE WHEN rel.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable, -- Added for pgAdmin4 (CASE WHEN (substring(array_to_string(rel.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean THEN true ELSE false END) AS autovacuum_custom, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/default/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/default/create.sql index ffb6b8489..8ea1b762b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/default/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/default/create.sql @@ -57,9 +57,8 @@ CREATE {% if data.relpersistence %}UNLOGGED {% endif %}TABLE {{conn|qtIdent(data {{CONSTRAINTS.EXCLUDE(conn, data.exclude_constraint)}}{% endif %} {% if data.like_relation or data.coll_inherits or data.columns|length > 0 or data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 or data.exclude_constraint|length > 0 %} -){% if data.relkind is defined and data.relkind == 'p' %} PARTITION BY {{ data.partition_scheme }} {% endif %} +){% endif %}{% if data.relkind is defined and data.relkind == 'p' %} PARTITION BY {{ data.partition_scheme }} {% endif %} -{% endif %} {### If we are inheriting it from another table(s) ###} {% if data.coll_inherits %} INHERITS ({% for val in data.coll_inherits %}{% if loop.index != 1 %}, {% endif %}{{val}}{% endfor %})