Hi, Please find the attached updated patch with the fixes. I have also considered the suggestions given by Aditya on different email thread.
Thanks, Khushboo On Wed, Jul 25, 2018 at 6:01 PM, Akshay Joshi <akshay.jo...@enterprisedb.com > wrote: > Hi Khushboo > > Following are my initial review comments: > > - Fix PEP-8 warnings. > - We should hide "Modulus" and "Remainder" columns for PG/EPAS 10 as > Hash partition is not supported in that. > - Primary key switch control on "columns" tab should be enabled for > partitioned table created on PG/EPAS 11. > - Please verify that Unique constraint are supported for PG/EPAS 11 or > not. > > Will do code review tomorrow. > > On Wed, Jul 25, 2018 at 4:29 PM, Khushboo Vashi < > khushboo.va...@enterprisedb.com> wrote: > >> Hi, >> >> >> Please find the attached patch for RM #3412. >> >> - Add support for PRIMARY KEY, FOREIGN KEY, indexes, and triggers on >> partitioned tables for PG 11 >> >> - Add support for partitioning by HASH key. >> >> >> Thanks, >> Khushboo >> > > > > -- > *Akshay Joshi* > > *Sr. Software Architect * > > > > *Phone: +91 20-3058-9517Mobile: +91 976-788-8246* >
diff --git a/docs/en_US/images/table_partition.png b/docs/en_US/images/table_partition.png new file mode 100644 index 0000000..2d6e999 Binary files /dev/null and b/docs/en_US/images/table_partition.png differ diff --git a/docs/en_US/table_dialog.rst b/docs/en_US/table_dialog.rst index 016fbd0..ba6a9b3 100644 --- a/docs/en_US/table_dialog.rst +++ b/docs/en_US/table_dialog.rst @@ -256,6 +256,31 @@ Use the fields in the **Like** box to specify which attributes of an existing ta * Move the *With storage?* switch to the *Yes* position to copy storage settings. * Move the *With comments?* switch to the *Yes* position to copy comments. +With PostgreSQL 10 forward, the *Partition* tab will be visible. + +Click the *Partition* tab to continue. + +.. image:: images/table_partition.png + :alt: Table dialog partition tab + +Use the fields in the *partition* tab to create the partitions for the table: + +* Select a partition type from the *Partition Type* selection box. There are 3 options available; Range, List and Hash. Hash option will only enable for PostgreSQL version >= 11. + +Use the *Partition Keys* panel to define the partition keys. Click the *Add* icon (+) to add each partition keys selection: + +* Select a partition key type in the *Keytype* field. +* Select a partition column in the *Column* field if Column option selected for *Keytype* field . +* Specify the expression in the *Expression* field if Expression option selected for the *Keytype* field. + +Use the *Partitions* panel to define the partitions of a table. Click the *Add* icon (+) to add each partition: + +* Move the *Operation* switch to *attach* to attach the partition, by default it is *create*. +* Use the *Name* field to add the name of the partition. +* If partition type is Range then *From* and *To* fields will be enabled. +* If partition type is List then *In* field will be enabled. +* If partition type is Hash then *Modulus* and *Remainder* fields will be enabled. + Click the *Parameter* tab to continue. .. image:: images/table_parameter.png diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/static/js/column.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/static/js/column.js index 582167a..95506ba 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/static/js/column.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/static/js/column.js @@ -205,7 +205,8 @@ define('pgadmin.node.column', [ m.top.get('primary_key').length > 0 && !_.isUndefined(m.top.get('primary_key').first().get('oid')) ) || ( - m.top.has('is_partitioned') && m.top.get('is_partitioned') + m.top.has('is_partitioned') && m.top.get('is_partitioned') && + m.top.node_info.server && m.top.node_info.server.version < 11000 )) ) { return true; @@ -235,7 +236,8 @@ define('pgadmin.node.column', [ // If table is partitioned table then disable if (m.top && !_.isUndefined(m.top.get('is_partitioned')) && - m.top.get('is_partitioned')) + m.top.get('is_partitioned') && m.top.node_info.server && + m.top.node_info.server.version < 11000) { setTimeout(function () { m.set('is_primary_key', false); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js index 9d11ec7..e3dd9dc 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js @@ -1061,13 +1061,15 @@ define('pgadmin.node.foreign_key', [ var t = pgBrowser.tree, i = item, d = itemData, parents = [], immediate_parent_table_found = false, - is_immediate_parent_table_partitioned = false; + is_immediate_parent_table_partitioned = false, + s_version = this.getTreeNodeHierarchy(i).server.version; + // To iterate over tree to check parent node while (i) { // If table is partitioned table then return false if (!immediate_parent_table_found && (d._type == 'table' || d._type == 'partition')) { immediate_parent_table_found = true; - if ('is_partitioned' in d && d.is_partitioned) { + if ('is_partitioned' in d && d.is_partitioned && s_version < 110000) { is_immediate_parent_table_partitioned = true; } } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js index e599b28..a9307d4 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js @@ -44,14 +44,15 @@ define('pgadmin.node.primary_key', [ var t = pgBrowser.tree, i = item, d = itemData, parents = [], immediate_parent_table_found = false, - is_immediate_parent_table_partitioned = false; + is_immediate_parent_table_partitioned = false, + s_version = this.getTreeNodeHierarchy(i).server.version; // To iterate over tree to check parent node while (i) { // If table is partitioned table then return false if (!immediate_parent_table_found && (d._type == 'table' || d._type == 'partition')) { immediate_parent_table_found = true; - if ('is_partitioned' in d && d.is_partitioned) { + if ('is_partitioned' in d && d.is_partitioned && s_version < 110000) { is_immediate_parent_table_partitioned = true; } } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/unique_constraint.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/unique_constraint.js index f8b8c2c..ae40561 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/unique_constraint.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/unique_constraint.js @@ -44,14 +44,15 @@ define('pgadmin.node.unique_constraint', [ var t = pgBrowser.tree, i = item, d = itemData, parents = [], immediate_parent_table_found = false, - is_immediate_parent_table_partitioned = false; + is_immediate_parent_table_partitioned = false, + s_version = this.getTreeNodeHierarchy(i).server.version; // To iterate over tree to check parent node while (i) { // If table is partitioned table then return false if (!immediate_parent_table_found && (d._type == 'table' || d._type == 'partition')) { immediate_parent_table_found = true; - if ('is_partitioned' in d && d.is_partitioned) { + if ('is_partitioned' in d && d.is_partitioned && s_version < 110000) { is_immediate_parent_table_partitioned = 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 1acdb8e..7279b15 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 @@ -75,8 +75,9 @@ class IndexesModule(CollectionNodeModule): if super(IndexesModule, self).BackendSupported(manager, **kwargs): conn = manager.connection(did=kwargs['did']) - # In case of partitioned table return false. - if 'tid' in kwargs and manager.version >= 100000: + # If PG version > 100000 and < 110000 then index is + # not supported for partitioned table. + if 'tid' in kwargs and 100000 <= manager.version < 110000: return not backend_supported(self, manager, **kwargs) if 'vid' not in kwargs: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js index 1da58ae..5732013 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js @@ -560,14 +560,15 @@ define('pgadmin.node.index', [ var t = pgBrowser.tree, i = item, d = itemData, parents = [], immediate_parent_table_found = false, - is_immediate_parent_table_partitioned = false; + is_immediate_parent_table_partitioned = false, + s_version = this.getTreeNodeHierarchy(i).server.version; // To iterate over tree to check parent node while (i) { // Do not allow creating index on partitioned tables. if (!immediate_parent_table_found && _.indexOf(['table', 'partition'], d._type) > -1) { immediate_parent_table_found = true; - if ('is_partitioned' in d && d.is_partitioned) { + if ('is_partitioned' in d && d.is_partitioned && s_version < 110000) { is_immediate_parent_table_partitioned = true; } } 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 80610cf..bd0cbf4 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 @@ -237,6 +237,8 @@ define('pgadmin.node.table_partition_utils', [ values_from: undefined, values_to: undefined, values_in: undefined, + values_modulus: undefined, + values_remainder: undefined, }, keys:['partition_name'], schema: [{ @@ -252,7 +254,7 @@ define('pgadmin.node.table_partition_utils', [ }, },{ id: 'partition_name', label: gettext('Name'), type: 'text', cell:'string', - cellHeaderClasses: 'width_percent_25', + cellHeaderClasses: 'width_percent_15', editable: function(m) { if (m instanceof Backbone.Model && m.isNew()) return true; @@ -261,11 +263,11 @@ define('pgadmin.node.table_partition_utils', [ },{ id: 'values_from', label: gettext('From'), type:'text', cell:Backgrid.Extension.StringDepCell, - cellHeaderClasses: 'width_percent_20', + cellHeaderClasses: 'width_percent_15', editable: function(m) { if(m.handler && m.handler.top && m.handler.top.attributes && - m.handler.top.attributes.partition_type == 'range' && + m.handler.top.attributes.partition_type === 'range' && m instanceof Backbone.Model && m.isNew()) return true; return false; @@ -273,11 +275,11 @@ define('pgadmin.node.table_partition_utils', [ },{ id: 'values_to', label: gettext('To'), type:'text', cell:Backgrid.Extension.StringDepCell, - cellHeaderClasses: 'width_percent_20', + cellHeaderClasses: 'width_percent_15', editable: function(m) { if(m.handler && m.handler.top && m.handler.top.attributes && - m.handler.top.attributes.partition_type == 'range' && + m.handler.top.attributes.partition_type === 'range' && m instanceof Backbone.Model && m.isNew()) return true; return false; @@ -285,11 +287,35 @@ define('pgadmin.node.table_partition_utils', [ },{ id: 'values_in', label: gettext('In'), type:'text', cell:Backgrid.Extension.StringDepCell, - cellHeaderClasses: 'width_percent_25', + cellHeaderClasses: 'width_percent_15', editable: function(m) { if(m.handler && m.handler.top && m.handler.top.attributes && - m.handler.top.attributes.partition_type == 'list' && + m.handler.top.attributes.partition_type === 'list' && + m instanceof Backbone.Model && m.isNew()) + return true; + return false; + }, + },{ + id: 'values_modulus', label: gettext('Modulus'), type:'int', + cell:Backgrid.Extension.StringDepCell, + cellHeaderClasses: 'width_percent_15', + editable: function(m) { + if(m.handler && m.handler.top && + m.handler.top.attributes && + m.handler.top.attributes.partition_type === 'hash' && + m instanceof Backbone.Model && m.isNew()) + return true; + return false; + }, + },{ + id: 'values_remainder', label: gettext('Remainder'), type:'int', + cell:Backgrid.Extension.StringDepCell, + cellHeaderClasses: 'width_percent_15 width_percent_20', + editable: function(m) { + if(m.handler && m.handler.top && + m.handler.top.attributes && + m.handler.top.attributes.partition_type === 'hash' && m instanceof Backbone.Model && m.isNew()) return true; return false; @@ -300,6 +326,8 @@ define('pgadmin.node.table_partition_utils', [ values_from = this.get('values_from'), values_to = this.get('values_to'), values_in = this.get('values_in'), + values_modulus = this.get('values_modulus'), + values_remainder = this.get('values_remainder'), msg; // Have to clear existing validation before initiating current state @@ -307,31 +335,43 @@ define('pgadmin.node.table_partition_utils', [ this.errorModel.clear(); if (_.isUndefined(partition_name) || _.isNull(partition_name) || - String(partition_name).replace(/^\s+|\s+$/g, '') == '') { + String(partition_name).replace(/^\s+|\s+$/g, '') === '') { msg = gettext('Partition name cannot be empty.'); this.errorModel.set('partition_name', msg); return msg; } - if (this.top.get('partition_type') == 'range') { + if (this.top.get('partition_type') === 'range') { if (_.isUndefined(values_from) || _.isNull(values_from) || - String(values_from).replace(/^\s+|\s+$/g, '') == '') { + String(values_from).replace(/^\s+|\s+$/g, '') === '') { msg = gettext('For range partition From field cannot be empty.'); this.errorModel.set('values_from', msg); return msg; } else if (_.isUndefined(values_to) || _.isNull(values_to) || - String(values_to).replace(/^\s+|\s+$/g, '') == '') { + String(values_to).replace(/^\s+|\s+$/g, '') === '') { msg = gettext('For range partition To field cannot be empty.'); this.errorModel.set('values_to', msg); return msg; } - } else if (this.top.get('partition_type') == 'list') { + } else if (this.top.get('partition_type') === 'list') { if (_.isUndefined(values_in) || _.isNull(values_in) || - String(values_in).replace(/^\s+|\s+$/g, '') == '') { + String(values_in).replace(/^\s+|\s+$/g, '') === '') { msg = gettext('For list partition In field cannot be empty.'); this.errorModel.set('values_in', msg); return msg; } + } else if (this.top.get('partition_type') === 'hash') { + if (_.isUndefined(values_modulus) || _.isNull(values_modulus) || + String(values_modulus).replace(/^\s+|\s+$/g, '') === '') { + msg = gettext('For hash partition Modulus field cannot be empty.'); + this.errorModel.set('values_modulus', msg); + return msg; + } else if (_.isUndefined(values_remainder) || _.isNull(values_remainder) || + String(values_remainder).replace(/^\s+|\s+$/g, '') === '') { + msg = gettext('For hash partition Remainder field cannot be empty.'); + this.errorModel.set('values_remainder', msg); + return msg; + } } return null; 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 530cd11..94b9ae1 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 @@ -593,7 +593,9 @@ define('pgadmin.node.table', [ control: 'unique-col-collection', columns : ['name', 'columns'], canAdd: function(m) { - if (m.get('is_partitioned')) { + if (m.get('is_partitioned') && !_.isUndefined(m.top.node_info) && !_.isUndefined(m.top.node_info.server) + && !_.isUndefined(m.top.node_info.server.version) && + m.top.node_info.server.version < 110000) { setTimeout(function() { var coll = m.get('primary_key'); coll.remove(coll.filter(function() { return true; })); @@ -620,7 +622,9 @@ define('pgadmin.node.table', [ canEdit: true, canDelete: true, deps:['is_partitioned'], control: 'unique-col-collection', canAdd: function(m) { - if (m.get('is_partitioned')) { + if (m.get('is_partitioned') && !_.isUndefined(m.top.node_info) && !_.isUndefined(m.top.node_info.server) + && !_.isUndefined(m.top.node_info.server.version) && + m.top.node_info.server.version < 110000) { setTimeout(function() { var coll = m.get('foreign_key'); coll.remove(coll.filter(function() { return true; })); @@ -656,7 +660,8 @@ define('pgadmin.node.table', [ control: 'unique-col-collection', columns : ['name', 'columns'], canAdd: function(m) { - if (m.get('is_partitioned')) { + if (m.get('is_partitioned') && !_.isUndefined(m.node_info) && !_.isUndefined(m.node_info.server) + && !_.isUndefined(m.node_info.server.version) && m.node_info.server.version < 110000) { setTimeout(function() { var coll = m.get('unique_constraint'); coll.remove(coll.filter(function() { return true; })); @@ -834,11 +839,22 @@ define('pgadmin.node.table', [ id: 'partition_type', label:gettext('Partition Type'), editable: false, type: 'select2', select2: {allowClear: false}, group: 'partition', deps: ['is_partitioned'], - options:[{ - label: gettext('Range'), value: 'range', - },{ - label: gettext('List'), value: 'list', - }], + options: function() { + var options = [{ + label: gettext('Range'), value: 'range', + },{ + label: gettext('List'), value: 'list', + }]; + + if(!_.isUndefined(this.node_info) && !_.isUndefined(this.node_info.server) + && !_.isUndefined(this.node_info.server.version) && + this.node_info.server.version >= 110000) { + options.push({ + label: gettext('Hash'), value: 'hash', + }); + } + return options; + }, mode:['create'], visible: function(m) { if(!_.isUndefined(m.node_info) && !_.isUndefined(m.node_info.server) @@ -963,7 +979,7 @@ define('pgadmin.node.table', [ canEdit: false, canDelete: true, customDeleteTitle: gettext('Detach Partition'), customDeleteMsg: gettext('Are you sure you wish to detach this partition?'), - columns:['is_attach', 'partition_name', 'values_from', 'values_to', 'values_in'], + columns:['is_attach', 'partition_name', 'values_from', 'values_to', 'values_in', 'values_modulus', 'values_remainder'], control: Backform.SubNodeCollectionControl.extend({ row: Backgrid.PartitionRow, initialize: function() { @@ -1040,6 +1056,8 @@ define('pgadmin.node.table', [ '</li><li> ', gettext('In: Enabled for list partition. Values must be comma(,) separated and quoted with single quote.'), '</li></ul></li></ul>', + gettext('Modulus/Remainder: Enabled for hash partition.'), + '</li></ul></li></ul>', ].join(''), visible: function(m) { if(!_.isUndefined(m.node_info) && !_.isUndefined(m.node_info.server) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/tests/test_table_add.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/tests/test_table_add.py index 4c3cde3..da30142 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/tests/test_table_add.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/tests/test_table_add.py @@ -36,6 +36,12 @@ class TableAddTestCase(BaseTestGenerator): server_min_version=100000, partition_type='list' ) + ), + ('Create Hash partitioned table with 2 partitions', + dict(url='/browser/table/obj/', + server_min_version=110000, + partition_type='hash' + ) ) ] @@ -93,13 +99,14 @@ class TableAddTestCase(BaseTestGenerator): "attoptions": [], "seclabels": [] }, - {"name": "DOJ", - "cltype": "date", - "attacl": [], - "is_primary_key": False, - "attoptions": [], - "seclabels": [] - } + { + "name": "DOJ", + "cltype": "date", + "attacl": [], + "is_primary_key": False, + "attoptions": [], + "seclabels": [] + } ], "exclude_constraint": [], "fillfactor": "", @@ -208,7 +215,9 @@ class TableAddTestCase(BaseTestGenerator): 'is_attach': False, 'partition_name': 'emp_2011' }] - else: + data['partition_keys'] = \ + [{'key_type': 'column', 'pt_column': 'DOJ'}] + elif self.partition_type == 'list': data['partitions'] = \ [{'values_in': "'2012-01-01', '2012-12-31'", 'is_attach': False, @@ -218,8 +227,22 @@ class TableAddTestCase(BaseTestGenerator): 'is_attach': False, 'partition_name': 'emp_2013' }] - data['partition_keys'] = \ - [{'key_type': 'column', 'pt_column': 'DOJ'}] + data['partition_keys'] = \ + [{'key_type': 'column', 'pt_column': 'DOJ'}] + else: + data['partitions'] = \ + [{'values_modulus': "24", + 'values_remainder': "3", + 'is_attach': False, + 'partition_name': 'emp_2016' + }, + {'values_modulus': "8", + 'values_remainder': "2", + 'is_attach': False, + 'partition_name': 'emp_2017' + }] + data['partition_keys'] = \ + [{'key_type': 'column', 'pt_column': 'empno'}] # Add table response = self.tester.post( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js index 85aab40..95dcc96 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js @@ -204,7 +204,9 @@ define('pgadmin.node.trigger', [ disabled: function(m) { // Disabled if table is a partitioned table. if (_.has(m, 'node_info') && _.has(m.node_info, 'table') && - _.has(m.node_info.table, 'is_partitioned') && m.node_info.table.is_partitioned) + _.has(m.node_info.table, 'is_partitioned') && + m.node_info.table.is_partitioned && m.node_info.server.version < 110000 + ) { setTimeout(function(){ m.set('is_row_trigger', false); 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 7264dd7..f210456 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 @@ -874,6 +874,7 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): # Table & Schema declaration so that we can use them in child nodes schema = data['schema'] table = data['name'] + is_partitioned = 'is_partitioned' in data and data['is_partitioned'] data = self._formatter(did, scid, tid, data) @@ -1139,7 +1140,7 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): # 5) Reverse engineered sql for PARTITIONS ########################################## """ - if 'is_partitioned' in data and data['is_partitioned']: + if is_partitioned: SQL = render_template("/".join([self.partition_template_path, 'nodes.sql']), scid=scid, tid=tid) @@ -1211,6 +1212,9 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): elif 'partition_type' in data \ and data['partition_type'] == 'list': partition_scheme = 'LIST (' + elif 'partition_type' in data \ + and data['partition_type'] == 'hash': + partition_scheme = 'HASH (' for row in data['partition_keys']: if row['key_type'] == 'column': @@ -2205,7 +2209,7 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): 'values_from': range_from, 'values_to': range_to }) - else: + elif data['partition_type'] == 'list': range_part = \ row['partition_value'].split('FOR VALUES IN (')[1] @@ -2215,6 +2219,20 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): 'partition_name': partition_name, 'values_in': range_in }) + else: + range_part = row['partition_value'].split( + 'FOR VALUES WITH (')[1].split(",") + range_modulus = range_part[0].strip().strip( + "modulus").strip() + range_remainder = range_part[1].strip().\ + strip(" remainder").strip(")").strip() + + partitions.append({ + 'oid': row['oid'], + 'partition_name': partition_name, + 'values_modulus': range_modulus, + 'values_remainder': range_remainder + }) data['partitions'] = partitions @@ -2256,10 +2274,26 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): part_data['partition_value'] = 'FOR VALUES FROM (' + from_str \ + ') TO (' + to_str + ')' - else: + + elif partitions['partition_type'] == 'list': range_in = row['values_in'].split(',') in_str = ', '.join("{0}".format(item) for item in range_in) - part_data['partition_value'] = 'FOR VALUES IN (' + in_str + ')' + part_data['partition_value'] = 'FOR VALUES IN (' + in_str\ + + ')' + + else: + range_modulus = row['values_modulus'].split(',') + range_remainder = row['values_remainder'].split(',') + + modulus_str = ', '.join("{0}".format(item) for item in + range_modulus) + remainder_str = ', '.join("{0}".format(item) for item in + range_remainder) + + part_data['partition_value'] = 'FOR VALUES WITH (MODULUS '\ + + modulus_str \ + + ', REMAINDER ' +\ + remainder_str + ')' if 'is_attach' in row and row['is_attach']: partition_sql = render_template(