mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Added multiple drop/delete functionality for the table constraints. Fixes #3900
This commit is contained in:
committed by
Akshay Joshi
parent
553eeb034d
commit
6e5dbf7beb
@@ -32,6 +32,7 @@ Bug fixes
|
|||||||
| `Issue #3495 <https://redmine.postgresql.org/issues/3495>`_ - Fixed an issue where the query tool unable to load the file which contains the BOM marker.
|
| `Issue #3495 <https://redmine.postgresql.org/issues/3495>`_ - Fixed an issue where the query tool unable to load the file which contains the BOM marker.
|
||||||
| `Issue #3523 <https://redmine.postgresql.org/issues/3523>`_ - Fixed an issue where right-clicking a browser object does not apply to the object on which right-click was fired.
|
| `Issue #3523 <https://redmine.postgresql.org/issues/3523>`_ - Fixed an issue where right-clicking a browser object does not apply to the object on which right-click was fired.
|
||||||
| `Issue #3645 <https://redmine.postgresql.org/issues/3645>`_ - Ensure that the start and end date should be deleted when clear the selection for pgAgent Job.
|
| `Issue #3645 <https://redmine.postgresql.org/issues/3645>`_ - Ensure that the start and end date should be deleted when clear the selection for pgAgent Job.
|
||||||
|
| `Issue #3900 <https://redmine.postgresql.org/issues/3900>`_ - Added multiple drop/delete functionality for the table constraints.
|
||||||
| `Issue #3947 <https://redmine.postgresql.org/issues/3947>`_ - Fixed copy-paste row issues in View/Edit Data.
|
| `Issue #3947 <https://redmine.postgresql.org/issues/3947>`_ - Fixed copy-paste row issues in View/Edit Data.
|
||||||
| `Issue #3972 <https://redmine.postgresql.org/issues/3972>`_ - Modified keyboard shortcuts in Query Tool for OSX native support.
|
| `Issue #3972 <https://redmine.postgresql.org/issues/3972>`_ - Modified keyboard shortcuts in Query Tool for OSX native support.
|
||||||
| `Issue #3988 <https://redmine.postgresql.org/issues/3988>`_ - Fixed cursor disappeared issue in the query editor for some of the characters when zoomed out.
|
| `Issue #3988 <https://redmine.postgresql.org/issues/3988>`_ - Fixed cursor disappeared issue in the query editor for some of the characters when zoomed out.
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
"""Implements Constraint Node"""
|
"""Implements Constraint Node"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
from flask import request
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
import pgadmin.browser.server_groups.servers.databases as database
|
import pgadmin.browser.server_groups.servers.databases as database
|
||||||
@@ -132,3 +134,48 @@ def proplist(**kwargs):
|
|||||||
response=res,
|
response=res,
|
||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route('/obj/<int:gid>/<int:sid>/<int:did>/<int:scid>/<int:tid>/',
|
||||||
|
methods=['DELETE'])
|
||||||
|
@blueprint.route('/delete/<int:gid>/<int:sid>/<int:did>/<int:scid>/<int:tid>/',
|
||||||
|
methods=['DELETE'])
|
||||||
|
def delete(**kwargs):
|
||||||
|
"""
|
||||||
|
Delete multiple constraints under the table.
|
||||||
|
Args:
|
||||||
|
**kwargs:
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
data = request.form if request.form else json.loads(
|
||||||
|
request.data, encoding='utf-8')
|
||||||
|
|
||||||
|
if 'delete' in request.base_url:
|
||||||
|
cmd = {"cmd": "delete"}
|
||||||
|
else:
|
||||||
|
cmd = {"cmd": "obj"}
|
||||||
|
res = []
|
||||||
|
module_wise_data = {}
|
||||||
|
|
||||||
|
for d in data['ids']:
|
||||||
|
if d['_type'] in module_wise_data:
|
||||||
|
module_wise_data[d['_type']].append(d['id'])
|
||||||
|
else:
|
||||||
|
module_wise_data[d['_type']] = [d['id']]
|
||||||
|
|
||||||
|
for name in ConstraintRegistry.registry:
|
||||||
|
if name in module_wise_data:
|
||||||
|
module = (ConstraintRegistry.registry[name])['nodeview']
|
||||||
|
view = module(**cmd)
|
||||||
|
request.data = json.dumps({'ids': module_wise_data[name]})
|
||||||
|
response = view.delete(**kwargs)
|
||||||
|
res = json.loads(response.data.decode('utf-8'))
|
||||||
|
if not res['success']:
|
||||||
|
return response
|
||||||
|
|
||||||
|
return make_json_response(
|
||||||
|
success=1,
|
||||||
|
info=gettext("Constraints dropped.")
|
||||||
|
)
|
||||||
|
|||||||
@@ -272,6 +272,9 @@ class CheckConstraintView(PGChildNodeView):
|
|||||||
tid=tid)
|
tid=tid)
|
||||||
status, res = self.conn.execute_dict(SQL)
|
status, res = self.conn.execute_dict(SQL)
|
||||||
|
|
||||||
|
for row in res['rows']:
|
||||||
|
row['_type'] = self.node_type
|
||||||
|
|
||||||
return res['rows']
|
return res['rows']
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
|
|||||||
@@ -339,6 +339,9 @@ class ExclusionConstraintView(PGChildNodeView):
|
|||||||
tid=tid)
|
tid=tid)
|
||||||
status, res = self.conn.execute_dict(SQL)
|
status, res = self.conn.execute_dict(SQL)
|
||||||
|
|
||||||
|
for row in res['rows']:
|
||||||
|
row['_type'] = self.node_type
|
||||||
|
|
||||||
return res['rows']
|
return res['rows']
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
|
|||||||
@@ -349,6 +349,9 @@ class ForeignKeyConstraintView(PGChildNodeView):
|
|||||||
tid=tid)
|
tid=tid)
|
||||||
status, res = self.conn.execute_dict(SQL)
|
status, res = self.conn.execute_dict(SQL)
|
||||||
|
|
||||||
|
for row in res['rows']:
|
||||||
|
row['_type'] = self.node_type
|
||||||
|
|
||||||
return res['rows']
|
return res['rows']
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
|
|||||||
@@ -359,6 +359,9 @@ class IndexConstraintView(PGChildNodeView):
|
|||||||
constraint_type=self.constraint_type)
|
constraint_type=self.constraint_type)
|
||||||
status, res = self.conn.execute_dict(SQL)
|
status, res = self.conn.execute_dict(SQL)
|
||||||
|
|
||||||
|
for row in res['rows']:
|
||||||
|
row['_type'] = self.node_type
|
||||||
|
|
||||||
return res['rows']
|
return res['rows']
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ define('pgadmin.node.constraints', [
|
|||||||
label: gettext('Constraints'),
|
label: gettext('Constraints'),
|
||||||
type: 'coll-constraints',
|
type: 'coll-constraints',
|
||||||
columns: ['name', 'comment'],
|
columns: ['name', 'comment'],
|
||||||
canDrop: false,
|
canDrop: true,
|
||||||
canDropCascade: false,
|
canDropCascade: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
import json
|
||||||
|
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
|
||||||
|
utils as schema_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||||
|
database_utils
|
||||||
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
|
from regression import parent_node_dict
|
||||||
|
from regression.python_test_utils import test_utils as utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.tests \
|
||||||
|
import utils as tables_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||||
|
constraints.check_constraint.tests import utils as chk_constraint_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||||
|
constraints.exclusion_constraint.tests import utils as exclusion_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||||
|
constraints.foreign_key.tests import utils as fk_utils
|
||||||
|
from pgadmin.browser.server_groups.servers.databases.schemas.tables.\
|
||||||
|
constraints.index_constraint.tests import utils as index_constraint_utils
|
||||||
|
|
||||||
|
|
||||||
|
class ConstraintDeleteMultipleTestCase(BaseTestGenerator):
|
||||||
|
"""This class will delete constraints under table node."""
|
||||||
|
scenarios = [
|
||||||
|
# Fetching default URL for table node.
|
||||||
|
('Delete Constraints', dict(url='/browser/constraints/obj/'))
|
||||||
|
]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.db_name = parent_node_dict["database"][-1]["db_name"]
|
||||||
|
schema_info = parent_node_dict["schema"][-1]
|
||||||
|
self.server_id = schema_info["server_id"]
|
||||||
|
self.db_id = schema_info["db_id"]
|
||||||
|
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
||||||
|
self.server_id, self.db_id)
|
||||||
|
if not db_con['data']["connected"]:
|
||||||
|
raise Exception("Could not connect to database to add a table.")
|
||||||
|
self.schema_id = schema_info["schema_id"]
|
||||||
|
self.schema_name = schema_info["schema_name"]
|
||||||
|
schema_response = schema_utils.verify_schemas(self.server,
|
||||||
|
self.db_name,
|
||||||
|
self.schema_name)
|
||||||
|
if not schema_response:
|
||||||
|
raise Exception("Could not find the schema to add a table.")
|
||||||
|
self.table_name = "table_constraint_delete_%s" % \
|
||||||
|
(str(uuid.uuid4())[1:8])
|
||||||
|
self.table_id = tables_utils.create_table(self.server,
|
||||||
|
self.db_name,
|
||||||
|
self.schema_name,
|
||||||
|
self.table_name)
|
||||||
|
# Create Check Constraints
|
||||||
|
self.check_constraint_name = "test_constraint_delete_%s" % \
|
||||||
|
(str(uuid.uuid4())[1:8])
|
||||||
|
self.check_constraint_id = \
|
||||||
|
chk_constraint_utils.create_check_constraint(
|
||||||
|
self.server, self.db_name, self.schema_name, self.table_name,
|
||||||
|
self.check_constraint_name)
|
||||||
|
|
||||||
|
self.check_constraint_name_1 = "test_constraint_delete1_%s" % (
|
||||||
|
str(uuid.uuid4())[1:8])
|
||||||
|
self.check_constraint_id_1 = \
|
||||||
|
chk_constraint_utils.create_check_constraint(
|
||||||
|
self.server, self.db_name, self.schema_name, self.table_name,
|
||||||
|
self.check_constraint_name_1)
|
||||||
|
|
||||||
|
# Create Exclusion Constraint
|
||||||
|
self.exclustion_constraint_name = "test_exclusion_get_%s" % (
|
||||||
|
str(uuid.uuid4())[1:8])
|
||||||
|
self.exclustion_constraint_id = \
|
||||||
|
exclusion_utils.create_exclusion_constraint(
|
||||||
|
self.server, self.db_name, self.schema_name, self.table_name,
|
||||||
|
self.exclustion_constraint_name
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create Foreign Key
|
||||||
|
self.foreign_table_name = "foreign_table_foreignkey_get_%s" % \
|
||||||
|
(str(uuid.uuid4())[1:8])
|
||||||
|
self.foreign_table_id = tables_utils.create_table(
|
||||||
|
self.server, self.db_name, self.schema_name,
|
||||||
|
self.foreign_table_name)
|
||||||
|
self.foreign_key_name = "test_foreignkey_get_%s" % \
|
||||||
|
(str(uuid.uuid4())[1:8])
|
||||||
|
self.foreign_key_id = fk_utils.create_foreignkey(
|
||||||
|
self.server, self.db_name, self.schema_name, self.table_name,
|
||||||
|
self.foreign_table_name)
|
||||||
|
|
||||||
|
# Create Primary Key
|
||||||
|
self.primary_key_name = "test_primary_key_get_%s" % \
|
||||||
|
(str(uuid.uuid4())[1:8])
|
||||||
|
self.primary_key_id = \
|
||||||
|
index_constraint_utils.create_index_constraint(
|
||||||
|
self.server, self.db_name, self.schema_name, self.table_name,
|
||||||
|
self.primary_key_name, "PRIMARY KEY")
|
||||||
|
|
||||||
|
# Create Unique Key constraint
|
||||||
|
self.unique_constraint_name = "test_unique_constraint_get_%s" % (
|
||||||
|
str(uuid.uuid4())[1:8])
|
||||||
|
|
||||||
|
self.unique_constraint_id = \
|
||||||
|
index_constraint_utils.create_index_constraint(
|
||||||
|
self.server, self.db_name, self.schema_name, self.table_name,
|
||||||
|
self.unique_constraint_name, "UNIQUE")
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
"""This function will delete constraints under table node."""
|
||||||
|
data = {'ids': [
|
||||||
|
{'id': self.check_constraint_id, '_type': 'check_constraint'},
|
||||||
|
{'id': self.check_constraint_id_1, '_type': 'check_constraint'},
|
||||||
|
{'id': self.exclustion_constraint_id,
|
||||||
|
'_type': 'exclustion_constraint'},
|
||||||
|
{'id': self.foreign_key_id, '_type': 'foreign_key'},
|
||||||
|
{'id': self.primary_key_id, '_type': 'index_constraint'},
|
||||||
|
{'id': self.unique_constraint_id, '_type': 'index_constraint'}
|
||||||
|
]}
|
||||||
|
response = self.tester.delete(self.url + str(utils.SERVER_GROUP) +
|
||||||
|
'/' + str(self.server_id) + '/' +
|
||||||
|
str(self.db_id) + '/' +
|
||||||
|
str(self.schema_id) + '/' +
|
||||||
|
str(self.table_id) + '/',
|
||||||
|
data=json.dumps(data),
|
||||||
|
content_type='html/json',
|
||||||
|
follow_redirects=True)
|
||||||
|
self.assertEquals(response.status_code, 200)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
# Disconnect the database
|
||||||
|
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||||
@@ -354,7 +354,13 @@ define([
|
|||||||
msg = undefined,
|
msg = undefined,
|
||||||
title = undefined;
|
title = undefined;
|
||||||
|
|
||||||
_.each(sel_row_models, function(r){ sel_rows.push(r.id); });
|
if (node.type && node.type == 'coll-constraints') {
|
||||||
|
// In order to identify the constraint type, the type should be passed to the server
|
||||||
|
sel_rows = sel_row_models.map(row => ({id: row.get('oid'), _type: row.get('_type')}));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sel_rows = sel_row_models.map(row => row.id);
|
||||||
|
}
|
||||||
|
|
||||||
if (sel_rows.length === 0) {
|
if (sel_rows.length === 0) {
|
||||||
Alertify.alert(gettext('Drop Multiple'),
|
Alertify.alert(gettext('Drop Multiple'),
|
||||||
|
|||||||
Reference in New Issue
Block a user