Added support to view multilevel partitioned tables. Fixes #4633.

This commit is contained in:
Akshay Joshi 2020-01-06 14:53:47 +05:30
parent d4ee869281
commit 2979424db5
4 changed files with 81 additions and 60 deletions

View File

@ -27,6 +27,7 @@ Bug fixes
| `Issue #4198 <https://redmine.postgresql.org/issues/4198>`_ - Fix syntax highlighting in code mirror for backslash and escape constant.
| `Issue #4506 <https://redmine.postgresql.org/issues/4506>`_ - Fix an issue where clicking on an empty textbox like fill factor or comments, considers it as change and enabled the save button.
| `Issue #4633 <https://redmine.postgresql.org/issues/4633>`_ - Added support to view multilevel partitioned tables.
| `Issue #4842 <https://redmine.postgresql.org/issues/4842>`_ - Ensure that constraints, indexes, rules, triggers, and compound triggers should be created on partitions.
| `Issue #4943 <https://redmine.postgresql.org/issues/4943>`_ - Added more information to the 'Database connected/disconnected' message.
| `Issue #4999 <https://redmine.postgresql.org/issues/4999>`_ - Rename some internal environment variables that could conflict with Kubernetes.

View File

@ -200,52 +200,27 @@ class PartitionsView(BaseTableView, DataTypeReader, VacuumSettings):
})
def children(self, **kwargs):
"""Build a list of treeview nodes from the child nodes."""
if 'sid' not in kwargs:
return precondition_required(
gettext('Required properties are missing.')
)
from pgadmin.utils.driver import get_driver
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
sid=kwargs['sid']
)
did = None
if 'did' in kwargs:
did = kwargs['did']
conn = manager.connection(did=did)
if not conn.connected():
return precondition_required(
gettext(
"Connection to the server has been lost."
)
)
def get_children_nodes(self, manager, **kwargs):
nodes = []
# treat partition table as normal table.
# replace tid with ptid and pop ptid from kwargs
if 'ptid' in kwargs:
ptid = kwargs.pop('ptid')
kwargs['tid'] = ptid
for module in self.blueprint.submodules:
if isinstance(module, PGChildModule):
if manager is not None and \
module.BackendSupported(manager, **kwargs):
# treat partition table as normal table.
# replace tid with ptid and pop ptid from kwargs
if 'ptid' in kwargs:
ptid = kwargs.pop('ptid')
kwargs['tid'] = ptid
nodes.extend(module.get_nodes(**kwargs))
else:
nodes.extend(module.get_nodes(**kwargs))
# Return sorted nodes based on label
return make_json_response(
data=sorted(
nodes, key=lambda c: c['label']
)
)
if manager is not None and \
self.blueprint.BackendSupported(manager, **kwargs):
nodes.extend(self.blueprint.get_nodes(**kwargs))
return nodes
@BaseTableView.check_precondition
def list(self, gid, sid, did, scid, tid):
@ -295,7 +270,7 @@ class PartitionsView(BaseTableView, DataTypeReader, VacuumSettings):
"""
SQL = render_template(
"/".join([self.partition_template_path, 'nodes.sql']),
scid=scid, tid=tid
scid=scid, tid=tid, ptid=ptid
)
status, rset = self.conn.execute_2darray(SQL)
if not status:

View File

@ -49,8 +49,7 @@ function(
sqlCreateHelp: 'sql-createtable.html',
dialogHelp: url_for('help.static', {'filename': 'table_dialog.html'}),
hasScriptTypes: ['create'],
height: '95%',
width: '85%',
width: '650px',
Init: function() {
/* Avoid mulitple registration of menus */
if (this.initialized)
@ -865,7 +864,7 @@ function(
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', 'is_default', 'values_from', 'values_to', 'values_in', 'values_modulus', 'values_remainder'],
control: Backform.SubNodeCollectionControl.extend({
row: Backgrid.PartitionRow,
initialize: function() {
@ -930,10 +929,30 @@ function(
},{
id: 'partition_note', label: gettext('Partition'),
type: 'note', group: 'partition',
text: gettext('The control above is used to Create/Attach/Detach partitions.<br>' +
'<ul><li>Create Mode: User will be able to create N number of partitions. Mode switch control is disabled in this scenario.</li>' +
'<li>Edit Mode: User will be able to create/attach/detach N number of partitions. ' +
'In attach mode there will be list of suitable tables to be attached.</li></ul>'),
text: [
'<ul><li>',
'<strong>', gettext('Create a table: '), '</strong>',
gettext('User can create multiple partitions while creating new partitioned table. Operation switch is disabled in this scenario.'),
'</li><li>',
'<strong>', gettext('Edit existing table: '), '</strong>',
gettext('User can create/attach/detach multiple partitions. In attach operation user can select table from the list of suitable tables to be attached.'),
'</li><li>',
'<strong>', gettext('Default: '), '</strong>',
gettext('The default partition can store rows that do not fall into any existing partitions range or list.'),
'</li><li>',
'<strong>', gettext('From/To/In input: '), '</strong>',
gettext('From/To/In input: Values for these fields must be quoted with single quote. For more than one partition key values must be comma(,) separated.'),
'</li><li>',
'<strong>', gettext('Example: From/To: '), '</strong>',
gettext('Enabled for range partition. Consider partitioned table with multiple keys of type Integer, then values should be specified like \'100\',\'200\'.'),
'</li><li>',
'<strong>', gettext('In: '), '</strong>',
gettext('Enabled for list partition. Values must be comma(,) separated and quoted with single quote.'),
'</li><li>',
'<strong>', gettext('Modulus/Remainder: '), '</strong>',
gettext('Enabled for hash partition.'),
'</li></ul>',
].join(''),
visible: function(m) {
if(!_.isUndefined(m.node_info) && !_.isUndefined(m.node_info.server)
&& !_.isUndefined(m.node_info.server.version) &&

View File

@ -343,10 +343,8 @@ class NodeView(with_metaclass(MethodViewType, View)):
def children(self, *args, **kwargs):
"""Build a list of treeview nodes from the child nodes."""
children = []
children = self.get_children_nodes(*args, **kwargs)
for module in self.blueprint.submodules:
children.extend(module.get_nodes(*args, **kwargs))
# Return sorted nodes based on label
return make_json_response(
data=sorted(
@ -354,8 +352,46 @@ class NodeView(with_metaclass(MethodViewType, View)):
)
)
def get_children_nodes(self, *args, **kwargs):
"""
Returns the list of children nodes for the current nodes. Override this
function for special cases only.
:param args:
:param kwargs: Parameters to generate the correct set of tree node.
:return: List of the children nodes
"""
children = []
for module in self.blueprint.submodules:
children.extend(module.get_nodes(*args, **kwargs))
return children
class PGChildNodeView(NodeView):
def get_children_nodes(self, manager, **kwargs):
"""
Returns the list of children nodes for the current nodes.
:param manager: Server Manager object
:param kwargs: Parameters to generate the correct set of browser tree
node
:return:
"""
nodes = []
for module in self.blueprint.submodules:
if isinstance(module, PGChildModule):
if (
manager is not None and
module.BackendSupported(manager, **kwargs)
):
nodes.extend(module.get_nodes(**kwargs))
else:
nodes.extend(module.get_nodes(**kwargs))
return nodes
def children(self, **kwargs):
"""Build a list of treeview nodes from the child nodes."""
@ -388,21 +424,11 @@ class PGChildNodeView(NodeView):
)
)
nodes = []
for module in self.blueprint.submodules:
if isinstance(module, PGChildModule):
if (
manager is not None and
module.BackendSupported(manager, **kwargs)
):
nodes.extend(module.get_nodes(**kwargs))
else:
nodes.extend(module.get_nodes(**kwargs))
# Return sorted nodes based on label
return make_json_response(
data=sorted(
nodes, key=lambda c: c['label']
self.get_children_nodes(manager, **kwargs),
key=lambda c: c['label']
)
)