mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
1) Added option to ignore the whitespaces while comparing objects in schema diff. Fixes #5468
2) Added server group name while selecting servers in schema diff. Fixes #5500 3) Fixed an issue where two identical tables showing different by schema diff tool. Fixes #5584
This commit is contained in:
parent
9f5e8962b5
commit
cb268075c2
Binary file not shown.
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 117 KiB |
@ -390,6 +390,9 @@ Expand the *Schema Diff* node to specify your display preferences.
|
|||||||
:alt: Preferences schema diff
|
:alt: Preferences schema diff
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
|
Use the *Ignore whitespaces* switch to ignores the whitespaces while comparing
|
||||||
|
the string objects. Whitespace includes space, tabs, and CRLF.
|
||||||
|
|
||||||
Use the *Open in new browser tab* switch to indicate if you would like Schema Diff
|
Use the *Open in new browser tab* switch to indicate if you would like Schema Diff
|
||||||
to open in a new tab.
|
to open in a new tab.
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ This release contains a number of bug fixes and new features since the release o
|
|||||||
New features
|
New features
|
||||||
************
|
************
|
||||||
|
|
||||||
|
| `Issue #5468 <https://redmine.postgresql.org/issues/5468>`_ - Added option to ignore the whitespaces while comparing objects in schema diff.
|
||||||
|
| `Issue #5500 <https://redmine.postgresql.org/issues/5500>`_ - Added server group name while selecting servers in schema diff.
|
||||||
| `Issue #5516 <https://redmine.postgresql.org/issues/5516>`_ - Added support of Row Security Policies.
|
| `Issue #5516 <https://redmine.postgresql.org/issues/5516>`_ - Added support of Row Security Policies.
|
||||||
| `Issue #5576 <https://redmine.postgresql.org/issues/5576>`_ - Improve error messaging if the storage and log directories cannot be created.
|
| `Issue #5576 <https://redmine.postgresql.org/issues/5576>`_ - Improve error messaging if the storage and log directories cannot be created.
|
||||||
|
|
||||||
@ -29,4 +31,5 @@ Bug fixes
|
|||||||
| `Issue #5507 <https://redmine.postgresql.org/issues/5507>`_ - Fixed connection and version number detection issue when the database server is upgraded.
|
| `Issue #5507 <https://redmine.postgresql.org/issues/5507>`_ - Fixed connection and version number detection issue when the database server is upgraded.
|
||||||
| `Issue #5521 <https://redmine.postgresql.org/issues/5521>`_ - Fixed an issue when dumping servers from a desktop pgAdmin app by providing an option '--sqlite-path'.
|
| `Issue #5521 <https://redmine.postgresql.org/issues/5521>`_ - Fixed an issue when dumping servers from a desktop pgAdmin app by providing an option '--sqlite-path'.
|
||||||
| `Issue #5539 <https://redmine.postgresql.org/issues/5539>`_ - Fixed typo in exception keyword.
|
| `Issue #5539 <https://redmine.postgresql.org/issues/5539>`_ - Fixed typo in exception keyword.
|
||||||
|
| `Issue #5584 <https://redmine.postgresql.org/issues/5584>`_ - Fixed an issue where two identical tables showing different by schema diff tool.
|
||||||
| `Issue #5592 <https://redmine.postgresql.org/issues/5592>`_ - Ensure that pgadmin should be able to connect to the server which has password more than 1000 characters.
|
| `Issue #5592 <https://redmine.postgresql.org/issues/5592>`_ - Ensure that pgadmin should be able to connect to the server which has password more than 1000 characters.
|
@ -158,7 +158,7 @@ def column_formatter(conn, tid, clid, data, edit_types_list=None,
|
|||||||
|
|
||||||
# We will need present type in edit mode
|
# We will need present type in edit mode
|
||||||
edit_types_list.append(data['cltype'])
|
edit_types_list.append(data['cltype'])
|
||||||
data['edit_types'] = edit_types_list
|
data['edit_types'] = sorted(edit_types_list)
|
||||||
|
|
||||||
data['cltype'] = DataTypeReader.parse_type_name(data['cltype'])
|
data['cltype'] = DataTypeReader.parse_type_name(data['cltype'])
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ def get_formatted_columns(conn, tid, data, other_columns,
|
|||||||
edit_types.keys())))
|
edit_types.keys())))
|
||||||
status, res = conn.execute_2darray(SQL)
|
status, res = conn.execute_2darray(SQL)
|
||||||
for row in res['rows']:
|
for row in res['rows']:
|
||||||
edit_types[row['main_oid']] = row['edit_types']
|
edit_types[row['main_oid']] = sorted(row['edit_types'])
|
||||||
|
|
||||||
for column in data['columns']:
|
for column in data['columns']:
|
||||||
column_formatter(conn, tid, column['attnum'], column,
|
column_formatter(conn, tid, column['attnum'], column,
|
||||||
|
@ -227,7 +227,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Schema Diff: Keys to ignore while comparing
|
# Schema Diff: Keys to ignore while comparing
|
||||||
keys_to_ignore = ['oid', 'relowner', 'schema',
|
keys_to_ignore = ['oid', 'relowner', 'schema', 'indclass',
|
||||||
'indrelid', 'nspname', 'oid-2']
|
'indrelid', 'nspname', 'oid-2']
|
||||||
|
|
||||||
def check_precondition(f):
|
def check_precondition(f):
|
||||||
@ -1068,11 +1068,11 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
create_req = True
|
create_req = True
|
||||||
|
|
||||||
if create_req:
|
if create_req:
|
||||||
diff = self.get_sql_from_index_diff(sid=tgt_params['sid'],
|
diff = self.get_sql_from_index_diff(sid=src_params['sid'],
|
||||||
did=tgt_params['did'],
|
did=src_params['did'],
|
||||||
scid=tgt_params['scid'],
|
scid=src_params['scid'],
|
||||||
tid=tgt_params['tid'],
|
tid=src_params['tid'],
|
||||||
idx=target['oid'],
|
idx=source['oid'],
|
||||||
diff_schema=target_schema,
|
diff_schema=target_schema,
|
||||||
drop_req=True)
|
drop_req=True)
|
||||||
else:
|
else:
|
||||||
|
@ -22,7 +22,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
table_keys_to_ignore = ['oid', 'schema', 'edit_types', 'attnum',
|
table_keys_to_ignore = ['oid', 'schema', 'edit_types', 'attnum',
|
||||||
'col_type', 'references', 'reltuples', 'oid-2',
|
'col_type', 'references', 'reltuples', 'oid-2',
|
||||||
'rows_cnt', 'seqrelid', 'atttypid', 'elemoid',
|
'rows_cnt', 'seqrelid', 'atttypid', 'elemoid',
|
||||||
'hastoasttable', 'relhassubclass']
|
'hastoasttable', 'relhassubclass', 'relacl_str']
|
||||||
|
|
||||||
constraint_keys_to_ignore = ['relname', 'nspname', 'parent_tbl',
|
constraint_keys_to_ignore = ['relname', 'nspname', 'parent_tbl',
|
||||||
'attrelid', 'adrelid', 'fknsp', 'confrelid',
|
'attrelid', 'adrelid', 'fknsp', 'confrelid',
|
||||||
@ -31,7 +31,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
|
|
||||||
trigger_keys_to_ignore = ['xmin', 'tgrelid', 'tgfoid', 'tfunction',
|
trigger_keys_to_ignore = ['xmin', 'tgrelid', 'tgfoid', 'tfunction',
|
||||||
'tgqual', 'tgconstraint']
|
'tgqual', 'tgconstraint']
|
||||||
index_keys_to_ignore = ['relowner', 'indrelid']
|
index_keys_to_ignore = ['relowner', 'indrelid', 'indclass']
|
||||||
|
|
||||||
keys_to_ignore = table_keys_to_ignore + constraint_keys_to_ignore \
|
keys_to_ignore = table_keys_to_ignore + constraint_keys_to_ignore \
|
||||||
+ trigger_keys_to_ignore + index_keys_to_ignore
|
+ trigger_keys_to_ignore + index_keys_to_ignore
|
||||||
@ -51,6 +51,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
'did': kwargs.get('target_did'),
|
'did': kwargs.get('target_did'),
|
||||||
'scid': kwargs.get('target_scid')}
|
'scid': kwargs.get('target_scid')}
|
||||||
|
|
||||||
|
ignore_whitespaces = kwargs.get('ignore_whitespaces')
|
||||||
status, target_schema = self.get_schema(**target_params)
|
status, target_schema = self.get_schema(**target_params)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=target_schema)
|
return internal_server_error(errormsg=target_schema)
|
||||||
@ -68,6 +69,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
target_tables,
|
target_tables,
|
||||||
self.node_type,
|
self.node_type,
|
||||||
self.blueprint.COLLECTION_LABEL,
|
self.blueprint.COLLECTION_LABEL,
|
||||||
|
ignore_whitespaces,
|
||||||
self.keys_to_ignore)
|
self.keys_to_ignore)
|
||||||
|
|
||||||
def ddl_compare(self, **kwargs):
|
def ddl_compare(self, **kwargs):
|
||||||
@ -225,7 +227,8 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
return different
|
return different
|
||||||
|
|
||||||
def get_sql_from_submodule_diff(self, source_params, target_params,
|
def get_sql_from_submodule_diff(self, source_params, target_params,
|
||||||
target_schema, source, target, diff_dict):
|
target_schema, source, target, diff_dict,
|
||||||
|
ignore_whitespaces):
|
||||||
"""
|
"""
|
||||||
This function returns the DDL/DML statements of the
|
This function returns the DDL/DML statements of the
|
||||||
submodules of table based on the comparison status.
|
submodules of table based on the comparison status.
|
||||||
@ -236,6 +239,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
:param source:
|
:param source:
|
||||||
:param target:
|
:param target:
|
||||||
:param diff_dict:
|
:param diff_dict:
|
||||||
|
:param ignore_whitespaces:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
# Get the difference result for source and target columns
|
# Get the difference result for source and target columns
|
||||||
@ -250,7 +254,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
target_params['diff_data'] = diff_dict
|
target_params['diff_data'] = diff_dict
|
||||||
diff = self.get_sql_from_table_diff(**target_params)
|
diff = self.get_sql_from_table_diff(**target_params)
|
||||||
|
|
||||||
ignore_sub_modules = ['column', 'constraints']
|
ignore_sub_modules = ['column', 'constraints', 'row_security_policy']
|
||||||
if self.manager.version < 100000:
|
if self.manager.version < 100000:
|
||||||
ignore_sub_modules.append('partition')
|
ignore_sub_modules.append('partition')
|
||||||
if self.manager.server_type == 'pg' or self.manager.version < 120000:
|
if self.manager.server_type == 'pg' or self.manager.version < 120000:
|
||||||
@ -314,7 +318,8 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
for key in intersect_keys:
|
for key in intersect_keys:
|
||||||
# Recursively Compare the two dictionary
|
# Recursively Compare the two dictionary
|
||||||
if not are_dictionaries_identical(
|
if not are_dictionaries_identical(
|
||||||
dict1[key], dict2[key], self.keys_to_ignore):
|
dict1[key], dict2[key], ignore_whitespaces,
|
||||||
|
self.keys_to_ignore):
|
||||||
|
|
||||||
diff_ddl = module_view.ddl_compare(
|
diff_ddl = module_view.ddl_compare(
|
||||||
source_params=source_params,
|
source_params=source_params,
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
@import '~codemirror/addon/scroll/simplescrollbars.css';
|
@import '~codemirror/addon/scroll/simplescrollbars.css';
|
||||||
|
|
||||||
@import '~slickgrid/slick.grid.css';
|
@import '~slickgrid/slick.grid.css';
|
||||||
|
@import '~slickgrid/slick-default-theme.css';
|
||||||
@import '~slickgrid/css/smoothness/jquery-ui-1.11.3.custom.css';
|
@import '~slickgrid/css/smoothness/jquery-ui-1.11.3.custom.css';
|
||||||
|
|
||||||
@import '../vendor/backgrid/backgrid.css';
|
@import '../vendor/backgrid/backgrid.css';
|
||||||
|
@ -24,6 +24,7 @@ from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
|||||||
from pgadmin.tools.schema_diff.model import SchemaDiffModel
|
from pgadmin.tools.schema_diff.model import SchemaDiffModel
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
|
from pgadmin.utils.preferences import Preferences
|
||||||
|
|
||||||
MODULE_NAME = 'schema_diff'
|
MODULE_NAME = 'schema_diff'
|
||||||
|
|
||||||
@ -79,6 +80,16 @@ class SchemaDiffModule(PgAdminModule):
|
|||||||
'will be opened in a new browser tab.')
|
'will be opened in a new browser tab.')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.preference.register(
|
||||||
|
'display', 'ignore_whitespaces',
|
||||||
|
gettext("Ignore whitespaces"), 'boolean', False,
|
||||||
|
category_label=gettext('Display'),
|
||||||
|
help_str=gettext('If set to True, then the Schema Diff '
|
||||||
|
'tool ignores the whitespaces while comparing '
|
||||||
|
'the string objects. Whitespace includes space, '
|
||||||
|
'tabs, and CRLF')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
blueprint = SchemaDiffModule(MODULE_NAME, __name__, static_url_path='/static')
|
blueprint = SchemaDiffModule(MODULE_NAME, __name__, static_url_path='/static')
|
||||||
|
|
||||||
@ -257,7 +268,7 @@ def servers():
|
|||||||
This function will return the list of servers for the specified
|
This function will return the list of servers for the specified
|
||||||
server id.
|
server id.
|
||||||
"""
|
"""
|
||||||
res = []
|
res = {}
|
||||||
try:
|
try:
|
||||||
"""Return a JSON document listing the server groups for the user"""
|
"""Return a JSON document listing the server groups for the user"""
|
||||||
driver = get_driver(PG_DEFAULT_DRIVER)
|
driver = get_driver(PG_DEFAULT_DRIVER)
|
||||||
@ -269,15 +280,19 @@ def servers():
|
|||||||
manager = driver.connection_manager(server.id)
|
manager = driver.connection_manager(server.id)
|
||||||
conn = manager.connection()
|
conn = manager.connection()
|
||||||
connected = conn.connected()
|
connected = conn.connected()
|
||||||
|
server_info = {
|
||||||
res.append({
|
|
||||||
"value": server.id,
|
"value": server.id,
|
||||||
"label": server.name,
|
"label": server.name,
|
||||||
"image": server_icon_and_background(connected, manager,
|
"image": server_icon_and_background(connected, manager,
|
||||||
server),
|
server),
|
||||||
"_id": server.id,
|
"_id": server.id,
|
||||||
"connected": connected,
|
"connected": connected
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if server.servers.name in res:
|
||||||
|
res[server.servers.name].append(server_info)
|
||||||
|
else:
|
||||||
|
res[server.servers.name] = [server_info]
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
app.logger.exception(e)
|
app.logger.exception(e)
|
||||||
@ -443,6 +458,9 @@ def compare(trans_id, source_sid, source_did, source_scid,
|
|||||||
diff_model_obj)
|
diff_model_obj)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
pref = Preferences.module('schema_diff')
|
||||||
|
ignore_whitespaces = pref.preference('ignore_whitespaces').get()
|
||||||
|
|
||||||
all_registered_nodes = SchemaDiffRegistry.get_registered_nodes()
|
all_registered_nodes = SchemaDiffRegistry.get_registered_nodes()
|
||||||
node_percent = round(100 / len(all_registered_nodes))
|
node_percent = round(100 / len(all_registered_nodes))
|
||||||
total_percent = 0
|
total_percent = 0
|
||||||
@ -462,7 +480,8 @@ def compare(trans_id, source_sid, source_did, source_scid,
|
|||||||
source_scid=source_scid,
|
source_scid=source_scid,
|
||||||
target_sid=target_sid,
|
target_sid=target_sid,
|
||||||
target_did=target_did,
|
target_did=target_did,
|
||||||
target_scid=target_scid)
|
target_scid=target_scid,
|
||||||
|
ignore_whitespaces=ignore_whitespaces)
|
||||||
|
|
||||||
if res is not None:
|
if res is not None:
|
||||||
comparison_result = comparison_result + res
|
comparison_result = comparison_result + res
|
||||||
|
@ -68,6 +68,7 @@ class SchemaDiffObjectCompare:
|
|||||||
'scid': kwargs.get('target_scid')
|
'scid': kwargs.get('target_scid')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ignore_whitespaces = kwargs.get('ignore_whitespaces')
|
||||||
status, target_schema = self.get_schema(kwargs.get('target_sid'),
|
status, target_schema = self.get_schema(kwargs.get('target_sid'),
|
||||||
kwargs.get('target_did'),
|
kwargs.get('target_did'),
|
||||||
kwargs.get('target_scid')
|
kwargs.get('target_scid')
|
||||||
@ -88,6 +89,7 @@ class SchemaDiffObjectCompare:
|
|||||||
target_schema, source, target,
|
target_schema, source, target,
|
||||||
self.node_type,
|
self.node_type,
|
||||||
gettext(self.blueprint.COLLECTION_LABEL),
|
gettext(self.blueprint.COLLECTION_LABEL),
|
||||||
|
ignore_whitespaces,
|
||||||
self.keys_to_ignore)
|
self.keys_to_ignore)
|
||||||
|
|
||||||
def ddl_compare(self, **kwargs):
|
def ddl_compare(self, **kwargs):
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"""Directory comparison"""
|
"""Directory comparison"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import string
|
||||||
from pgadmin.tools.schema_diff.model import SchemaDiffModel
|
from pgadmin.tools.schema_diff.model import SchemaDiffModel
|
||||||
|
|
||||||
count = 1
|
count = 1
|
||||||
@ -20,7 +21,7 @@ list_keys_array = ['name', 'colname', 'argid', 'token', 'option', 'conname',
|
|||||||
|
|
||||||
def compare_dictionaries(view_object, source_params, target_params,
|
def compare_dictionaries(view_object, source_params, target_params,
|
||||||
target_schema, source_dict, target_dict, node,
|
target_schema, source_dict, target_dict, node,
|
||||||
node_label,
|
node_label, ignore_whitespaces,
|
||||||
ignore_keys=None):
|
ignore_keys=None):
|
||||||
"""
|
"""
|
||||||
This function will compare the two dictionaries.
|
This function will compare the two dictionaries.
|
||||||
@ -33,6 +34,7 @@ def compare_dictionaries(view_object, source_params, target_params,
|
|||||||
:param target_dict: Second Dictionary
|
:param target_dict: Second Dictionary
|
||||||
:param node: node type
|
:param node: node type
|
||||||
:param node_label: node label
|
:param node_label: node label
|
||||||
|
:param ignore_whitespaces: If set the True then ignore whitespaces
|
||||||
:param ignore_keys: List of keys that will be ignored while comparing
|
:param ignore_keys: List of keys that will be ignored while comparing
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
@ -139,7 +141,8 @@ def compare_dictionaries(view_object, source_params, target_params,
|
|||||||
target_object_id = target_dict[key]['oid']
|
target_object_id = target_dict[key]['oid']
|
||||||
|
|
||||||
# Recursively Compare the two dictionary
|
# Recursively Compare the two dictionary
|
||||||
if are_dictionaries_identical(dict1[key], dict2[key], ignore_keys):
|
if are_dictionaries_identical(dict1[key], dict2[key],
|
||||||
|
ignore_whitespaces, ignore_keys):
|
||||||
identical.append({
|
identical.append({
|
||||||
'id': count,
|
'id': count,
|
||||||
'type': node,
|
'type': node,
|
||||||
@ -177,7 +180,7 @@ def compare_dictionaries(view_object, source_params, target_params,
|
|||||||
view_object.get_sql_from_table_diff(**temp_tgt_params)
|
view_object.get_sql_from_table_diff(**temp_tgt_params)
|
||||||
diff_ddl = view_object.get_sql_from_submodule_diff(
|
diff_ddl = view_object.get_sql_from_submodule_diff(
|
||||||
temp_src_params, temp_tgt_params, target_schema,
|
temp_src_params, temp_tgt_params, target_schema,
|
||||||
dict1[key], dict2[key], diff_dict)
|
dict1[key], dict2[key], diff_dict, ignore_whitespaces)
|
||||||
else:
|
else:
|
||||||
temp_src_params = copy.deepcopy(source_params)
|
temp_src_params = copy.deepcopy(source_params)
|
||||||
temp_tgt_params = copy.deepcopy(target_params)
|
temp_tgt_params = copy.deepcopy(target_params)
|
||||||
@ -213,11 +216,13 @@ def compare_dictionaries(view_object, source_params, target_params,
|
|||||||
return source_only + target_only + different + identical
|
return source_only + target_only + different + identical
|
||||||
|
|
||||||
|
|
||||||
def are_lists_identical(source_list, target_list, ignore_keys):
|
def are_lists_identical(source_list, target_list, ignore_whitespaces,
|
||||||
|
ignore_keys):
|
||||||
"""
|
"""
|
||||||
This function is used to compare two list.
|
This function is used to compare two list.
|
||||||
:param source_list:
|
:param source_list:
|
||||||
:param target_list:
|
:param target_list:
|
||||||
|
:param ignore_whitespaces: ignore whitespaces
|
||||||
:param ignore_keys: ignore keys to compare
|
:param ignore_keys: ignore keys to compare
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
@ -231,6 +236,7 @@ def are_lists_identical(source_list, target_list, ignore_keys):
|
|||||||
if type(source_list[index]) is dict:
|
if type(source_list[index]) is dict:
|
||||||
if not are_dictionaries_identical(source_list[index],
|
if not are_dictionaries_identical(source_list[index],
|
||||||
target_list[index],
|
target_list[index],
|
||||||
|
ignore_whitespaces,
|
||||||
ignore_keys):
|
ignore_keys):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
@ -239,12 +245,14 @@ def are_lists_identical(source_list, target_list, ignore_keys):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def are_dictionaries_identical(source_dict, target_dict, ignore_keys):
|
def are_dictionaries_identical(source_dict, target_dict, ignore_whitespaces,
|
||||||
|
ignore_keys):
|
||||||
"""
|
"""
|
||||||
This function is used to recursively compare two dictionaries with
|
This function is used to recursively compare two dictionaries with
|
||||||
same keys.
|
same keys.
|
||||||
:param source_dict: source dict
|
:param source_dict: source dict
|
||||||
:param target_dict: target dict
|
:param target_dict: target dict
|
||||||
|
:param ignore_whitespaces: If set to True then ignore whitespaces
|
||||||
:param ignore_keys: ignore keys to compare
|
:param ignore_keys: ignore keys to compare
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
@ -275,7 +283,9 @@ def are_dictionaries_identical(source_dict, target_dict, ignore_keys):
|
|||||||
|
|
||||||
if type(source_dict[key]) is dict:
|
if type(source_dict[key]) is dict:
|
||||||
if not are_dictionaries_identical(source_dict[key],
|
if not are_dictionaries_identical(source_dict[key],
|
||||||
target_dict[key], ignore_keys):
|
target_dict[key],
|
||||||
|
ignore_whitespaces,
|
||||||
|
ignore_keys):
|
||||||
return False
|
return False
|
||||||
elif type(source_dict[key]) is list:
|
elif type(source_dict[key]) is list:
|
||||||
# Sort the source and target list on the basis of
|
# Sort the source and target list on the basis of
|
||||||
@ -284,10 +294,25 @@ def are_dictionaries_identical(source_dict, target_dict, ignore_keys):
|
|||||||
target_dict[key])
|
target_dict[key])
|
||||||
# Compare the source and target lists
|
# Compare the source and target lists
|
||||||
if not are_lists_identical(source_dict[key], target_dict[key],
|
if not are_lists_identical(source_dict[key], target_dict[key],
|
||||||
|
ignore_whitespaces,
|
||||||
ignore_keys):
|
ignore_keys):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if source_dict[key] != target_dict[key]:
|
source_value = source_dict[key]
|
||||||
|
target_value = target_dict[key]
|
||||||
|
|
||||||
|
# If ignore_whitespaces is True then check the source_value and
|
||||||
|
# target_value if of type string. If the values is of type string
|
||||||
|
# then using translate function ignore all the whitespaces.
|
||||||
|
if ignore_whitespaces:
|
||||||
|
if isinstance(source_value, str):
|
||||||
|
source_value = source_value.translate(
|
||||||
|
str.maketrans('', '', string.whitespace))
|
||||||
|
if isinstance(target_value, str):
|
||||||
|
target_value = target_value.translate(
|
||||||
|
str.maketrans('', '', string.whitespace))
|
||||||
|
|
||||||
|
if source_value != target_value:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -124,16 +124,36 @@ let SchemaDiffSelect2Control =
|
|||||||
' <%=required ? "required" : ""%><%= select2.multiple ? " multiple>" : ">" %>',
|
' <%=required ? "required" : ""%><%= select2.multiple ? " multiple>" : ">" %>',
|
||||||
' <%=select2.first_empty ? " <option></option>" : ""%>',
|
' <%=select2.first_empty ? " <option></option>" : ""%>',
|
||||||
' <% for (var i=0; i < options.length; i++) {%>',
|
' <% for (var i=0; i < options.length; i++) {%>',
|
||||||
' <% var option = options[i]; %>',
|
' <% if (options[i].group) { %>',
|
||||||
' <option ',
|
' <% var group = options[i].group; %>',
|
||||||
' <% if (option.image) { %> data-image=<%=option.image%> <%}%>',
|
' <% if (options[i].optval) { %> <% var option_length = options[i].optval.length; %>',
|
||||||
' <% if (option.connected) { %> data-connected=connected <%}%>',
|
' <optgroup label="<%=group%>">',
|
||||||
' value=<%- formatter.fromRaw(option.value) %>',
|
' <% for (var subindex=0; subindex < option_length; subindex++) {%>',
|
||||||
' <% if (option.selected) {%>selected="selected"<%} else {%>',
|
' <% var option = options[i].optval[subindex]; %>',
|
||||||
' <% if (!select2.multiple && option.value === rawValue) {%>selected="selected"<%}%>',
|
' <option ',
|
||||||
' <% if (select2.multiple && rawValue && rawValue.indexOf(option.value) != -1){%>selected="selected" data-index="rawValue.indexOf(option.value)"<%}%>',
|
' <% if (option.image) { %> data-image=<%=option.image%> <%}%>',
|
||||||
' <%}%>',
|
' <% if (option.connected) { %> data-connected=connected <%}%>',
|
||||||
' <%= disabled ? "disabled" : ""%>><%-option.label%></option>',
|
' value=<%- formatter.fromRaw(option.value) %>',
|
||||||
|
' <% if (option.selected) {%>selected="selected"<%} else {%>',
|
||||||
|
' <% if (!select2.multiple && option.value === rawValue) {%>selected="selected"<%}%>',
|
||||||
|
' <% if (select2.multiple && rawValue && rawValue.indexOf(option.value) != -1){%>selected="selected" data-index="rawValue.indexOf(option.value)"<%}%>',
|
||||||
|
' <%}%>',
|
||||||
|
' <%= disabled ? "disabled" : ""%>><%-option.label%></option>',
|
||||||
|
' <%}%>',
|
||||||
|
' </optgroup>',
|
||||||
|
' <%}%>',
|
||||||
|
' <%} else {%>',
|
||||||
|
' <% var option = options[i]; %>',
|
||||||
|
' <option ',
|
||||||
|
' <% if (option.image) { %> data-image=<%=option.image%> <%}%>',
|
||||||
|
' <% if (option.connected) { %> data-connected=connected <%}%>',
|
||||||
|
' value=<%- formatter.fromRaw(option.value) %>',
|
||||||
|
' <% if (option.selected) {%>selected="selected"<%} else {%>',
|
||||||
|
' <% if (!select2.multiple && option.value === rawValue) {%>selected="selected"<%}%>',
|
||||||
|
' <% if (select2.multiple && rawValue && rawValue.indexOf(option.value) != -1){%>selected="selected" data-index="rawValue.indexOf(option.value)"<%}%>',
|
||||||
|
' <%}%>',
|
||||||
|
' <%= disabled ? "disabled" : ""%>><%-option.label%></option>',
|
||||||
|
' <%}%>',
|
||||||
' <%}%>',
|
' <%}%>',
|
||||||
' </select>',
|
' </select>',
|
||||||
' <% if (helpMessage && helpMessage.length) { %>',
|
' <% if (helpMessage && helpMessage.length) { %>',
|
||||||
|
@ -556,6 +556,15 @@ export default class SchemaDiffUI {
|
|||||||
fields: [{
|
fields: [{
|
||||||
name: 'source_sid', label: false,
|
name: 'source_sid', label: false,
|
||||||
control: SchemaDiffSelect2Control,
|
control: SchemaDiffSelect2Control,
|
||||||
|
transform: function(data) {
|
||||||
|
let group_template_options = [];
|
||||||
|
for (let key in data) {
|
||||||
|
if (data.hasOwnProperty(key)) {
|
||||||
|
group_template_options.push({'group': key, 'optval': data[key]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return group_template_options;
|
||||||
|
},
|
||||||
url: url_for('schema_diff.servers'),
|
url: url_for('schema_diff.servers'),
|
||||||
select2: {
|
select2: {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
@ -636,6 +645,15 @@ export default class SchemaDiffUI {
|
|||||||
}, {
|
}, {
|
||||||
name: 'target_sid', label: false,
|
name: 'target_sid', label: false,
|
||||||
control: SchemaDiffSelect2Control,
|
control: SchemaDiffSelect2Control,
|
||||||
|
transform: function(data) {
|
||||||
|
let group_template_options = [];
|
||||||
|
for (let key in data) {
|
||||||
|
if (data.hasOwnProperty(key)) {
|
||||||
|
group_template_options.push({'group': key, 'optval': data[key]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return group_template_options;
|
||||||
|
},
|
||||||
group: 'target',
|
group: 'target',
|
||||||
url: url_for('schema_diff.servers'),
|
url: url_for('schema_diff.servers'),
|
||||||
select2: {
|
select2: {
|
||||||
|
Loading…
Reference in New Issue
Block a user