Added support to compare schemas and databases in schema diff. Fixes #5891

This commit is contained in:
Akshay Joshi 2020-10-27 16:36:10 +05:30
parent 5284a1c66b
commit b76bb58378
34 changed files with 468 additions and 62 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 KiB

After

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 247 KiB

View File

@ -12,6 +12,7 @@ New features
| `Issue #3318 <https://redmine.postgresql.org/issues/3318>`_ - Added support to download utility files at the client-side.
| `Issue #4230 <https://redmine.postgresql.org/issues/4230>`_ - Added support to rename query tool and debugger tabs title.
| `Issue #4232 <https://redmine.postgresql.org/issues/4232>`_ - Added tab title placeholder for Query Tool, View/Edit Data, and Debugger.
| `Issue #5891 <https://redmine.postgresql.org/issues/5891>`_ - Added support to compare schemas and databases in schema diff.
Housekeeping
************

View File

@ -5,7 +5,7 @@
********************
**Schema Diff** is a feature that allows you to compare objects between
two databases. Use the *Tools* menu to access Schema Diff.
two databases or two schemas. Use the *Tools* menu to access Schema Diff.
The Schema Diff feature allows you to:
@ -18,16 +18,21 @@ The Schema Diff feature allows you to:
* Generate synchronization scripts.
**Note** - The source and target database servers must be of the same major
version.
**Note:**
Click on *Schema Diff* under the *Tools* menu to open a selection panel. Choose
the source and target servers, and databases that will be
compared. After selecting the objects, click on the *Compare* button.
* The source and target database servers must be of the same major version.
* If you compare two **schemas** then dependencies won't be resolved.
Click on *Schema Diff* under the *Tools* menu to open a selection panel.
To compare **databases** choose the source and target servers, and databases.
To compare **schemas** choose the source and target servers, databases, and schemas.
After selecting the objects, click on the *Compare* button.
You can open multiple copies of *Schema Diff* in individual tabs
simultaneously. To close a copy of Schema Diff, click the *X* in the
upper-right hand corner of the tab bar.
upper-right hand corner of the tab bar. You can rename the panel title by
right-clicking and select the "Rename Panel" option.
.. image:: images/schema_diff_dialog.png
:alt: schema diff dialog

View File

@ -700,6 +700,7 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
json_resp: True then return json response
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
SQL = render_template("/".join([self.template_path,
self._PROPERTIES_SQL]),
@ -711,6 +712,8 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
return gone(self.not_found_error_msg())
data = res['rows'][0]
if target_schema:
data['schema'] = target_schema
SQL = render_template("/".join([self.template_path,
self._CREATE_SQL]),
@ -811,14 +814,20 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
if target_schema:
data['schema'] = target_schema
sql, name = self.get_sql(gid=gid, sid=sid, data=data, scid=scid,
coid=oid)
else:
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, coid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, coid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, coid=oid,
json_resp=False)

View File

@ -721,6 +721,7 @@ AND relkind != 'c'))"""
json_resp: True then return json response
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
SQL = render_template("/".join([self.template_path,
self._PROPERTIES_SQL]),
@ -732,6 +733,8 @@ AND relkind != 'c'))"""
return gone(self.not_found_error_msg())
data = res['rows'][0]
if target_schema:
data['basensp'] = target_schema
# Get Type Length and Precision
data.update(self._parse_type(data['fulltype']))
@ -949,8 +952,11 @@ AND relkind != 'c'))"""
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
if target_schema:
data['schema'] = target_schema
sql, name = self.get_sql(gid=gid, sid=sid, scid=scid,
data=data, doid=oid,
is_schema_diff=True)
@ -958,6 +964,9 @@ AND relkind != 'c'))"""
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, doid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, doid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, doid=oid,
json_resp=False)

View File

@ -827,6 +827,7 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
json_resp: True then return json response
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
status, data = self._fetch_properties(gid, sid, did, scid, foid,
inherits=True)
@ -841,6 +842,8 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
col_data.append(c)
data['columns'] = col_data
if target_schema:
data['basensp'] = target_schema
# Parse Privileges
if 'acl' in data:
@ -1515,6 +1518,7 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
@ -1524,6 +1528,9 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, foid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, foid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, foid=oid,
json_resp=False)

View File

@ -904,6 +904,7 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare):
:param json_resp: True then return json response
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
try:
sql = render_template(
@ -928,6 +929,22 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare):
"FTS Configuration node.")
)
# Used for schema diff tool
if target_schema:
data = {'schema': scid}
# Fetch schema name from schema oid
sql = render_template("/".join([self.template_path,
'schema.sql']),
data=data,
conn=self.conn,
)
status, schema = self.conn.execute_scalar(sql)
if not status:
return internal_server_error(errormsg=schema)
res = res.replace(schema, target_schema)
if not json_resp:
return res
@ -1013,6 +1030,7 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
@ -1021,6 +1039,9 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare):
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, cfgid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, cfgid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, cfgid=oid,
json_resp=False)

View File

@ -800,6 +800,7 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare):
:param json_resp: True then return json response
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
sql = render_template(
"/".join([self.template_path, self._PROPERTIES_SQL]),
@ -843,6 +844,8 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare):
# Replace schema oid with schema name
res['rows'][0]['schema'] = schema
if target_schema:
res['rows'][0]['schema'] = target_schema
sql = render_template("/".join([self.template_path,
self._CREATE_SQL]),
@ -938,6 +941,7 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
@ -946,6 +950,9 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare):
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, dcid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, dcid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, dcid=oid,
json_resp=False)

View File

@ -849,6 +849,7 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
:param json_resp: True then return json response
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
try:
sql = render_template(
@ -874,6 +875,22 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
)
)
# Used for schema diff tool
if target_schema:
data = {'schema': scid}
# Fetch schema name from schema oid
sql = render_template("/".join([self.template_path,
'schema.sql']),
data=data,
conn=self.conn,
)
status, schema = self.conn.execute_scalar(sql)
if not status:
return internal_server_error(errormsg=schema)
res = res.replace(schema, target_schema)
if not json_resp:
return res
@ -959,6 +976,7 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
@ -967,6 +985,9 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, pid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pid=oid,
json_resp=False)

View File

@ -729,6 +729,7 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
:param json_resp: True then return json response
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
sql = render_template(
"/".join([self.template_path, 'sql.sql']),
@ -751,6 +752,22 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
"FTS Template node.")
)
# Used for schema diff tool
if target_schema:
data = {'schema': scid}
# Fetch schema name from schema oid
sql = render_template("/".join([self.template_path,
'schema.sql']),
data=data,
conn=self.conn,
)
status, schema = self.conn.execute_scalar(sql)
if not status:
return internal_server_error(errormsg=schema)
res = res.replace(schema, target_schema)
if not json_resp:
return res
@ -832,6 +849,7 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
@ -840,6 +858,9 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, tid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
json_resp=False)

View File

@ -1085,6 +1085,7 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
json_resp:
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
resp_data = self._fetch_properties(gid, sid, did, scid, fnid)
# Most probably this is due to error
@ -1128,6 +1129,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
status, res = self.conn.execute_2darray(sql)
if not status:
return internal_server_error(errormsg=res)
elif target_schema:
res['rows'][0]['nspname'] = target_schema
# Add newline and tab before each argument to format
name_with_default_args = self.qtIdent(
@ -1173,6 +1176,9 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
status, res = self.conn.execute_2darray(sql)
if not status:
return internal_server_error(errormsg=res)
elif target_schema:
res['rows'][0]['nspname'] = target_schema
resp_data['pronamespace'] = target_schema
# Add newline and tab before each argument to format
name_with_default_args = self.qtIdent(
@ -1389,7 +1395,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
fun_change_args = ['lanname', 'prosrc', 'probin', 'prosrc_c',
'provolatile', 'proisstrict', 'prosecdef',
'proparallel', 'procost', 'proleakproof',
'arguments', 'prorows', 'prosupportfunc']
'arguments', 'prorows', 'prosupportfunc',
'prorettypename']
data['change_func'] = False
for arg in fun_change_args:
@ -1828,8 +1835,11 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
if target_schema:
data['schema'] = target_schema
status, sql = self._get_sql(gid=gid, sid=sid, did=did, scid=scid,
data=data, fnid=oid, is_sql=False,
is_schema_diff=True)
@ -1843,6 +1853,9 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, fnid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, fnid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, fnid=oid,
json_resp=False)

View File

@ -582,8 +582,12 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
pkgid = kwargs.get('pkgid', None)
sqltab = kwargs.get('sqltab', False)
is_schema_diff = kwargs.get('is_schema_diff', None)
target_schema = kwargs.get('target_schema', None)
data['schema'] = self.schema
if target_schema:
data['schema'] = target_schema
else:
data['schema'] = self.schema
if pkgid is not None and not sqltab:
return self.get_sql_with_pkgid(scid, pkgid, data, is_schema_diff)
@ -687,6 +691,7 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
"""
is_schema_diff = kwargs.get('is_schema_diff', None)
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
try:
sql = render_template(
@ -719,10 +724,13 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
res['rows'][0].setdefault(row['deftype'], []).append(priv)
result = res['rows'][0]
if target_schema:
result['schema'] = target_schema
sql, name = self.getSQL(data=result, scid=scid, pkgid=pkgid,
sqltab=True,
is_schema_diff=is_schema_diff)
is_schema_diff=is_schema_diff,
target_schema=target_schema)
# Most probably this is due to error
if not isinstance(sql, str):
@ -847,13 +855,20 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
if target_schema:
data['schema'] = target_schema
sql, name = self.getSQL(data=data, scid=scid, pkgid=oid)
else:
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, pkgid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pkgid=oid,
is_schema_diff=True, json_resp=False,
target_schema=target_schema)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pkgid=oid,
is_schema_diff=True, json_resp=False)

View File

@ -696,6 +696,7 @@ class SequenceView(PGChildNodeView, SchemaDiffObjectCompare):
json_resp: json response or plain text response
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
sql = render_template(
"/".join([self.template_path, self._PROPERTIES_SQL]),
@ -725,6 +726,8 @@ class SequenceView(PGChildNodeView, SchemaDiffObjectCompare):
row['cycled'] = rset1['rows'][0]['is_cycled']
result = res['rows'][0]
if target_schema:
result['schema'] = target_schema
result = self._formatter(result, scid, seid)
sql, name = self.get_SQL(gid, sid, did, result, scid)
@ -942,13 +945,19 @@ class SequenceView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
if target_schema:
data['schema'] = target_schema
sql, name = self.get_SQL(gid, sid, did, data, scid, oid)
else:
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, seid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, seid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, seid=oid,
json_resp=False)

View File

@ -181,6 +181,8 @@ class SynonymView(PGChildNodeView, SchemaDiffObjectCompare):
{'get': 'get_target_objects'}]
})
keys_to_ignore = ['oid', 'oid-2', 'schema', 'synobjschema']
def check_precondition(f):
"""
This function will behave as a decorator which will checks
@ -666,6 +668,7 @@ class SynonymView(PGChildNodeView, SchemaDiffObjectCompare):
json_resp:
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
SQL = render_template("/".join([self.template_path,
self._PROPERTIES_SQL]),
@ -679,6 +682,9 @@ class SynonymView(PGChildNodeView, SchemaDiffObjectCompare):
else:
return gone(self.not_found_error_msg())
if target_schema:
data['schema'] = target_schema
SQL = render_template("/".join([self.template_path,
self._CREATE_SQL]),
data=data, conn=self.conn, comment=True)
@ -768,13 +774,19 @@ class SynonymView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
if target_schema:
data['schema'] = target_schema
sql, name = self.get_sql(gid, sid, data, scid, oid)
else:
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, syid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, syid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, syid=oid,
json_resp=False)

View File

@ -1245,12 +1245,13 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings,
This function will create sql on the basis the difference of 2 tables
"""
data = dict()
res = None
did = kwargs['did']
scid = kwargs['scid']
tid = kwargs['tid']
diff_data = kwargs['diff_data'] if 'diff_data' in kwargs else None
json_resp = kwargs['json_resp'] if 'json_resp' in kwargs else True
target_schema = kwargs['target_schema'] \
if 'target_schema' in kwargs else None
if diff_data:
return self._fetch_sql(did, scid, tid, diff_data, json_resp)
@ -1275,6 +1276,9 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings,
# Update autovacuum properties
self.update_autovacuum_properties(data)
if target_schema:
data['schema'] = target_schema
sql, partition_sql = BaseTableView.get_reverse_engineered_sql(
self, did=did, scid=scid, tid=tid, main_sql=main_sql,
data=data, json_resp=json_resp)

View File

@ -876,6 +876,7 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
sql, name = compound_trigger_utils.get_sql(self.conn,
@ -913,17 +914,21 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare):
data['columns'] = self._column_details(tid, columns)
data = trigger_definition(data)
sql = self._check_and_add_compound_trigger(tid, data)
sql = self._check_and_add_compound_trigger(tid, data,
target_schema)
return sql
def _check_and_add_compound_trigger(self, tid, data):
def _check_and_add_compound_trigger(self, tid, data, target_schema):
"""
This get compound trigger and check for disable.
:param tid: Table Id.
:param data: Data.
:param diff_schema: schema diff check.
:param target_schema: schema diff check.
"""
if target_schema:
data['schema'] = target_schema
sql, name = compound_trigger_utils.get_sql(self.conn,
data,
tid,
@ -989,6 +994,7 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare):
source = kwargs.get('source')
target = kwargs.get('target')
comp_status = kwargs.get('comp_status')
target_schema = kwargs.get('target_schema', None)
diff = ''
if comp_status == 'source_only':
@ -997,7 +1003,8 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare):
did=src_params['did'],
scid=src_params['scid'],
tid=src_params['tid'],
oid=source['oid'])
oid=source['oid'],
target_schema=target_schema)
elif comp_status == 'target_only':
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
sid=tgt_params['sid'],

View File

@ -844,8 +844,9 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
tid = kwargs.get('tid')
idx = kwargs.get('idx')
data = kwargs.get('data', None)
create_mode = kwargs.get('create_mode', None)
target_schema = kwargs.get('target_schema', None)
drop_req = kwargs.get('drop_req', False)
sql = ''
if data:
@ -859,9 +860,9 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
sql = sql.strip('\n').strip(' ')
elif create_mode:
elif target_schema:
sql = index_utils.get_reverse_engineered_sql(
self.conn, schema=self.schema,
self.conn, schema=target_schema,
table=self.table, did=did, tid=tid, idx=idx,
datlastsysoid=self.datlastsysoid,
template_path=None, with_header=False)
@ -1070,6 +1071,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
source = kwargs.get('source')
target = kwargs.get('target')
comp_status = kwargs.get('comp_status')
tgt_schema = kwargs.get('target_schema', None)
diff = ''
if comp_status == 'source_only':
@ -1078,7 +1080,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
scid=src_params['scid'],
tid=src_params['tid'],
idx=source['oid'],
create_mode=True)
target_schema=tgt_schema)
elif comp_status == 'target_only':
diff = self.delete(gid=1, sid=tgt_params['sid'],
did=tgt_params['did'], scid=tgt_params['scid'],
@ -1104,7 +1106,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
scid=src_params['scid'],
tid=src_params['tid'],
idx=source['oid'],
create_mode=True,
target_schema=tgt_schema,
drop_req=True)
else:
diff = self.get_sql_from_index_diff(sid=tgt_params['sid'],

View File

@ -614,8 +614,8 @@ class RowSecurityView(PGChildNodeView):
oid = kwargs.get('plid')
data = kwargs.get('data', None)
drop_req = kwargs.get('drop_req', False)
target_schema = kwargs.get('target_schema', None)
sql = ''
if data:
data['schema'] = self.schema
data['table'] = self.table
@ -626,8 +626,12 @@ class RowSecurityView(PGChildNodeView):
sql = sql.strip('\n').strip(' ')
else:
schema = self.schema
if target_schema:
schema = target_schema
sql = row_security_policies_utils.get_reverse_engineered_sql(
self.conn, schema=self.schema, table=self.table, scid=scid,
self.conn, schema=schema, table=self.table, scid=scid,
plid=oid, datlastsysoid=self.datlastsysoid, with_header=False)
drop_sql = ''
@ -688,6 +692,7 @@ class RowSecurityView(PGChildNodeView):
tgt_params = kwargs.get('target_params')
source = kwargs.get('source')
target = kwargs.get('target')
target_schema = kwargs.get('target_schema')
comp_status = kwargs.get('comp_status')
diff = ''
@ -697,7 +702,8 @@ class RowSecurityView(PGChildNodeView):
did=src_params['did'],
scid=src_params['scid'],
tid=src_params['tid'],
plid=source['oid'])
plid=source['oid'],
target_schema=target_schema)
elif comp_status == 'target_only':
diff = self.delete(gid=1,
sid=tgt_params['sid'],
@ -724,7 +730,8 @@ class RowSecurityView(PGChildNodeView):
did=src_params['did'],
scid=src_params['scid'],
tid=src_params['tid'],
plid=source['oid'])
plid=source['oid'],
target_schema=target_schema)
return delete_sql + diff
diff = self.get_sql_from_diff(gid=tgt_params['gid'],

View File

@ -529,6 +529,7 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
@ -551,12 +552,28 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare):
data=data, o_data=old_data
)
else:
RuleView._check_schema_diff(target_schema, res_data)
sql = render_template("/".join(
[self.template_path, self._CREATE_SQL]),
data=res_data, display_comments=True)
return sql
@ staticmethod
def _check_schema_diff(target_schema, res_data):
"""
Check for schema diff, if yes then replace source schema with target
schema.
diff_schema: schema diff schema
res_data: response from properties sql.
"""
if target_schema and 'statements' in res_data:
# Replace the source schema with the target schema
res_data['statements'] = \
res_data['statements'].replace(
res_data['schema'], target_schema)
res_data['schema'] = target_schema
@check_precondition
def dependents(self, gid, sid, did, scid, tid, rid):
"""

View File

@ -57,6 +57,10 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
source_tables = {}
target_tables = {}
status, target_schema = self.get_schema(**target_params)
if not status:
return internal_server_error(errormsg=target_schema)
if 'scid' in source_params and source_params['scid'] is not None:
source_tables = self.fetch_tables(**source_params)
@ -71,6 +75,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
return compare_dictionaries(view_object=self,
source_params=source_params,
target_params=target_params,
target_schema=target_schema,
source_dict=source_tables,
target_dict=target_tables,
node=self.node_type,
@ -241,6 +246,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
"""
source_params = kwargs.get('source_params')
target_params = kwargs.get('target_params')
target_schema = kwargs.get('target_schema')
source = kwargs.get('source')
target = kwargs.get('target')
diff_dict = kwargs.get('diff_dict')
@ -293,20 +299,21 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
added = dict1_keys - dict2_keys
diff = SchemaDiffTableCompare._compare_source_only(
added, module_view, source_params, target_params,
dict1, diff)
dict1, diff, target_schema)
# Keys that are available in target and missing in source.
removed = dict2_keys - dict1_keys
diff = SchemaDiffTableCompare._compare_target_only(
removed, module_view, source_params, target_params,
dict2, diff)
dict2, diff, target_schema)
# Keys that are available in both source and target.
other_param = {
"dict1": dict1,
"dict2": dict2,
"source": source,
"target": target
"target": target,
"target_schema": target_schema
}
diff = self._compare_source_and_target(
intersect_keys, module_view, source_params,
@ -316,11 +323,12 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
@staticmethod
def _compare_source_only(added, module_view, source_params, target_params,
dict1, diff):
dict1, diff, target_schema):
for item in added:
source_ddl = module_view.ddl_compare(
source_params=source_params,
target_params=target_params,
target_schema=target_schema,
source=dict1[item],
target=None,
comp_status='source_only'
@ -331,11 +339,12 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
@staticmethod
def _compare_target_only(removed, module_view, source_params,
target_params, dict2, diff):
target_params, dict2, diff, target_schema):
for item in removed:
target_ddl = module_view.ddl_compare(
source_params=source_params,
target_params=target_params,
target_schema=target_schema,
source=None,
target=dict2[item],
comp_status='target_only'
@ -351,6 +360,8 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
dict2 = kwargs['dict2']
source = kwargs['source']
target = kwargs['target']
target_schema = kwargs['target_schema']
for key in intersect_keys:
# Recursively Compare the two dictionary
if not are_dictionaries_identical(
@ -358,6 +369,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
diff_ddl = module_view.ddl_compare(
source_params=source_params,
target_params=target_params,
target_schema=target_schema,
source=dict1[key],
target=dict2[key],
comp_status='different',

View File

@ -866,6 +866,7 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
SQL, name = trigger_utils.get_sql(
@ -884,6 +885,9 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare):
only_sql=True)
else:
schema = self.schema
if target_schema:
schema = target_schema
SQL = trigger_utils.get_reverse_engineered_sql(
self.conn, schema=schema, table=self.table, tid=tid,
trid=oid, datlastsysoid=self.datlastsysoid,
@ -1052,6 +1056,7 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare):
tgt_params = kwargs.get('target_params')
source = kwargs.get('source')
target = kwargs.get('target')
target_schema = kwargs.get('target_schema')
comp_status = kwargs.get('comp_status')
diff = ''
@ -1061,7 +1066,8 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare):
did=src_params['did'],
scid=src_params['scid'],
tid=src_params['tid'],
oid=source['oid'])
oid=source['oid'],
target_schema=target_schema)
elif comp_status == 'target_only':
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
sid=tgt_params['sid'],

View File

@ -1373,6 +1373,7 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
json_resp: True then return json response
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
SQL = render_template(
"/".join([self.template_path,
@ -1390,6 +1391,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
)
# Making copy of output for future use
data = dict(res['rows'][0])
if target_schema:
data['schema'] = target_schema
SQL = render_template("/".join([self.template_path, self._ACL_SQL]),
scid=scid, tid=tid)
@ -1521,14 +1524,20 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
if target_schema:
data['schema'] = target_schema
sql, name = self.get_sql(gid=gid, sid=sid, scid=scid,
data=data, tid=oid)
else:
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, tid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
json_resp=False)

View File

@ -1371,6 +1371,7 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
This function will generate sql to render into the sql panel
"""
json_resp = kwargs.get('json_resp', True)
target_schema = kwargs.get('target_schema', None)
display_comments = True
if not json_resp:
@ -1390,6 +1391,10 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
return gone(self.not_found_error_msg())
result = res['rows'][0]
if target_schema:
result['definition'] = result['definition'].replace(
result['schema'], target_schema)
result['schema'] = target_schema
# sending result to formtter
frmtd_reslt = self.formatter(result)
@ -1689,8 +1694,11 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
oid = kwargs.get('oid')
data = kwargs.get('data', None)
drop_sql = kwargs.get('drop_sql', False)
target_schema = kwargs.get('target_schema', None)
if data:
if target_schema:
data['schema'] = target_schema
sql, name_or_error = self.getSQL(gid, sid, did, data, oid)
if sql.find('DROP VIEW') != -1:
sql = gettext("""
@ -1703,6 +1711,9 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
if drop_sql:
sql = self.delete(gid=gid, sid=sid, did=did,
scid=scid, vid=oid, only_sql=True)
elif target_schema:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, vid=oid,
target_schema=target_schema, json_resp=False)
else:
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, vid=oid,
json_resp=False)

View File

@ -30,6 +30,7 @@ from pgadmin.utils.constants import PREF_LABEL_DISPLAY, MIMETYPE_APP_JS,\
from sqlalchemy import or_
MODULE_NAME = 'schema_diff'
COMPARE_MSG = gettext("Comparing objects...")
class SchemaDiffModule(PgAdminModule):
@ -64,7 +65,9 @@ class SchemaDiffModule(PgAdminModule):
'schema_diff.panel',
'schema_diff.servers',
'schema_diff.databases',
'schema_diff.compare',
'schema_diff.schemas',
'schema_diff.compare_database',
'schema_diff.compare_schema',
'schema_diff.poll',
'schema_diff.ddl_compare',
'schema_diff.connect_server',
@ -430,32 +433,53 @@ def databases(sid):
@blueprint.route(
'/compare/<int:trans_id>/<int:source_sid>/<int:source_did>/'
'<int:target_sid>/<int:target_did>',
'/schemas/<int:sid>/<int:did>',
methods=["GET"],
endpoint="compare"
endpoint="schemas"
)
@login_required
def compare(trans_id, source_sid, source_did, target_sid, target_did):
def schemas(sid, did):
"""
This function will compare the two schemas.
This function will return the list of schemas for the specified
server id and database id.
"""
# Check the transaction and connection status
res = []
try:
schemas = get_schemas(sid, did)
if schemas is not None:
for sch in schemas:
res.append({
"value": sch['_id'],
"label": sch['label'],
"_id": sch['_id'],
"image": sch['icon'],
})
except Exception as e:
app.logger.exception(e)
return make_json_response(data=res)
@blueprint.route(
'/compare_database/<int:trans_id>/<int:source_sid>/<int:source_did>/'
'<int:target_sid>/<int:target_did>',
methods=["GET"],
endpoint="compare_database"
)
@login_required
def compare_database(trans_id, source_sid, source_did, target_sid, target_did):
"""
This function will compare the two databases.
"""
# Check the pre validation before compare
status, error_msg, diff_model_obj, session_obj = \
check_transaction_status(trans_id)
if error_msg == ERROR_MSG_TRANS_ID_NOT_FOUND:
return make_json_response(success=0, errormsg=error_msg, status=404)
# Server version compatibility check
status, msg = check_version_compatibility(source_sid, target_sid)
compare_pre_validation(trans_id, source_sid, target_sid)
if not status:
return make_json_response(success=0, errormsg=msg, status=428)
return error_msg
comparison_result = []
diff_model_obj.set_comparison_info(gettext("Comparing objects..."), 0)
diff_model_obj.set_comparison_info(COMPARE_MSG, 0)
update_session_diff_transaction(trans_id, session_obj,
diff_model_obj)
@ -552,6 +576,60 @@ def compare(trans_id, source_sid, source_did, target_sid, target_did):
return make_json_response(data=comparison_result)
@blueprint.route(
'/compare_schema/<int:trans_id>/<int:source_sid>/<int:source_did>/'
'<int:source_scid>/<int:target_sid>/<int:target_did>/<int:target_scid>',
methods=["GET"],
endpoint="compare_schema"
)
@login_required
def compare_schema(trans_id, source_sid, source_did, source_scid,
target_sid, target_did, target_scid):
"""
This function will compare the two schema.
"""
# Check the pre validation before compare
status, error_msg, diff_model_obj, session_obj = \
compare_pre_validation(trans_id, source_sid, target_sid)
if not status:
return error_msg
comparison_result = []
diff_model_obj.set_comparison_info(COMPARE_MSG, 0)
update_session_diff_transaction(trans_id, session_obj,
diff_model_obj)
try:
all_registered_nodes = SchemaDiffRegistry.get_registered_nodes()
node_percent = round(100 / len(all_registered_nodes))
total_percent = 0
comparison_schema_result, total_percent = \
compare_schema_objects(
trans_id=trans_id, session_obj=session_obj,
source_sid=source_sid, source_did=source_did,
source_scid=source_scid, target_sid=target_sid,
target_did=target_did, target_scid=target_scid,
schema_name=gettext('Schema Objects'),
diff_model_obj=diff_model_obj,
total_percent=total_percent,
node_percent=node_percent)
comparison_result = \
comparison_result + comparison_schema_result
msg = gettext("Successfully compare the specified schemas.")
total_percent = 100
diff_model_obj.set_comparison_info(msg, total_percent)
# Update the message and total percentage done in session object
update_session_diff_transaction(trans_id, session_obj, diff_model_obj)
except Exception as e:
app.logger.exception(e)
return make_json_response(data=comparison_result)
@blueprint.route(
'/poll/<int:trans_id>', methods=["GET"], endpoint="poll"
)
@ -573,7 +651,7 @@ def poll(trans_id):
msg, diff_percentage = diff_model_obj.get_comparison_info()
if diff_percentage == 100:
diff_model_obj.set_comparison_info(gettext("Comparing objects..."), 0)
diff_model_obj.set_comparison_info(COMPARE_MSG, 0)
update_session_diff_transaction(trans_id, session_obj,
diff_model_obj)
@ -755,9 +833,13 @@ def compare_schema_objects(**kwargs):
for node_name, node_view in all_registered_nodes.items():
view = SchemaDiffRegistry.get_node_view(node_name)
if hasattr(view, 'compare'):
msg = gettext('Comparing {0} of schema \'{1}\''). \
format(gettext(view.blueprint.collection_label),
gettext(schema_name))
if schema_name == 'Schema Objects':
msg = gettext('Comparing {0} '). \
format(gettext(view.blueprint.collection_label))
else:
msg = gettext('Comparing {0} of schema \'{1}\''). \
format(gettext(view.blueprint.collection_label),
gettext(schema_name))
app.logger.debug(msg)
diff_model_obj.set_comparison_info(msg, total_percent)
# Update the message and total percentage in session object
@ -832,3 +914,28 @@ def fetch_compare_schemas(source_sid, source_did, target_sid, target_did):
'in_both_database': in_both_database}
return schema_result
def compare_pre_validation(trans_id, source_sid, target_sid):
"""
This function is used to validate transaction id and version compatibility
:param trans_id:
:param source_sid:
:param target_sid:
:return:
"""
status, error_msg, diff_model_obj, session_obj = \
check_transaction_status(trans_id)
if error_msg == ERROR_MSG_TRANS_ID_NOT_FOUND:
res = make_json_response(success=0, errormsg=error_msg, status=404)
return False, res, None, None
# Server version compatibility check
status, msg = check_version_compatibility(source_sid, target_sid)
if not status:
res = make_json_response(success=0, errormsg=msg, status=428)
return False, res, None, None
return True, '', diff_model_obj, session_obj

View File

@ -12,12 +12,13 @@
from flask import render_template
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
from pgadmin.utils.ajax import internal_server_error
from pgadmin.tools.schema_diff.directory_compare import compare_dictionaries
class SchemaDiffObjectCompare:
keys_to_ignore = ['oid', 'oid-2', 'is_sys_obj']
keys_to_ignore = ['oid', 'oid-2', 'is_sys_obj', 'schema']
@staticmethod
def get_schema(sid, did, scid):
@ -62,6 +63,12 @@ class SchemaDiffObjectCompare:
source = {}
target = {}
status, target_schema = self.get_schema(kwargs.get('target_sid'),
kwargs.get('target_did'),
kwargs.get('target_scid'))
if not status:
return internal_server_error(errormsg=target_schema)
if group_name == 'Database Objects':
source = self.fetch_objects_to_compare(**source_params)
target = self.fetch_objects_to_compare(**target_params)
@ -83,6 +90,7 @@ class SchemaDiffObjectCompare:
return compare_dictionaries(view_object=self,
source_params=source_params,
target_params=target_params,
target_schema=target_schema,
source_dict=source,
target_dict=target,
node=self.node_type,

View File

@ -36,6 +36,7 @@ def _get_source_list(**kwargs):
node_label = kwargs.get('node_label')
group_name = kwargs.get('group_name')
source_schema_name = kwargs.get('source_schema_name')
target_schema = kwargs.get('target_schema')
global count
source_only = []
@ -50,6 +51,7 @@ def _get_source_list(**kwargs):
temp_src_params['json_resp'] = False
source_ddl = \
view_object.get_sql_from_table_diff(**temp_src_params)
temp_src_params.update({'target_schema': target_schema})
diff_ddl = view_object.get_sql_from_table_diff(**temp_src_params)
source_dependencies = \
view_object.get_table_submodules_dependencies(
@ -65,6 +67,7 @@ def _get_source_list(**kwargs):
temp_src_params['fsid'] = source_dict[item]['fsid']
source_ddl = view_object.get_sql_from_diff(**temp_src_params)
temp_src_params.update({'target_schema': target_schema})
diff_ddl = view_object.get_sql_from_diff(**temp_src_params)
source_dependencies = view_object.get_dependencies(
view_object.conn, source_object_id, where=None,
@ -223,6 +226,7 @@ def _get_identical_and_different_list(intersect_keys, source_dict, target_dict,
source_params = kwargs['source_params']
target_params = kwargs['target_params']
group_name = kwargs['group_name']
target_schema = kwargs.get('target_schema')
for key in intersect_keys:
source_object_id, target_object_id = \
get_source_target_oid(source_dict, target_dict, key)
@ -281,7 +285,8 @@ def _get_identical_and_different_list(intersect_keys, source_dict, target_dict,
diff_ddl = view_object.get_sql_from_submodule_diff(
source_params=temp_src_params,
target_params=temp_tgt_params,
source=dict1[key], target=dict2[key], diff_dict=diff_dict)
source=dict1[key], target=dict2[key], diff_dict=diff_dict,
target_schema=target_schema)
else:
temp_src_params = copy.deepcopy(source_params)
temp_tgt_params = copy.deepcopy(target_params)
@ -303,7 +308,7 @@ def _get_identical_and_different_list(intersect_keys, source_dict, target_dict,
show_system_objects=None, is_schema_diff=True)
target_ddl = view_object.get_sql_from_diff(**temp_tgt_params)
temp_tgt_params.update(
{'data': diff_dict})
{'data': diff_dict, 'target_schema': target_schema})
diff_ddl = view_object.get_sql_from_diff(**temp_tgt_params)
different.append({
@ -336,6 +341,7 @@ def compare_dictionaries(**kwargs):
view_object = kwargs.get('view_object')
source_params = kwargs.get('source_params')
target_params = kwargs.get('target_params')
target_schema = kwargs.get('target_schema')
group_name = kwargs.get('group_name')
source_dict = kwargs.get('source_dict')
target_dict = kwargs.get('target_dict')
@ -364,7 +370,8 @@ def compare_dictionaries(**kwargs):
view_object=view_object,
node_label=node_label,
group_name=group_name,
source_schema_name=source_schema_name)
source_schema_name=source_schema_name,
target_schema=target_schema)
target_only = []
# Keys that are available in target and missing in source.
@ -389,7 +396,8 @@ def compare_dictionaries(**kwargs):
"ignore_keys": ignore_keys,
"source_params": source_params,
"target_params": target_params,
"group_name": group_name
"group_name": group_name,
"target_schema": target_schema
}
identical, different = _get_identical_and_different_list(
@ -507,7 +515,8 @@ def are_dictionaries_identical(source_dict, target_dict, ignore_keys):
current_app.logger.debug(
"Schema Diff: Object name: '{0}', Source Value: '{1}', "
"Target Value: '{2}', Key: '{3}'".format(
source_dict['name'], source_value, target_value, key))
source_dict['name'] if 'name' in source_dict else '',
source_value, target_value, key))
return False
return True

View File

@ -105,7 +105,7 @@ let SchemaDiffSelect2Control =
controlsClassName: 'pgadmin-controls pg-el-sm-11 pg-el-12',
}),
className: function() {
return 'pgadmin-controls pg-el-sm-6';
return 'pgadmin-controls pg-el-sm-4';
},
events: {
'focus select': 'clearInvalid',

View File

@ -43,8 +43,10 @@ export default class SchemaDiffUI {
this.model = new Backbone.Model({
source_sid: undefined,
source_did: undefined,
source_scid: undefined,
target_sid: undefined,
target_did: undefined,
target_scid: undefined,
source_ddl: undefined,
target_ddl: undefined,
diff_ddl: undefined,
@ -162,7 +164,12 @@ export default class SchemaDiffUI {
url_params[key] = parseInt(val, 10);
});
var baseUrl = url_for('schema_diff.compare', url_params);
var baseUrl = url_for('schema_diff.compare_database', url_params);
// If compare two schema then change the base url
if (url_params['source_scid'] != '' && !_.isUndefined(url_params['source_scid']) &&
url_params['target_scid'] != '' && !_.isUndefined(url_params['target_scid'])) {
baseUrl = url_for('schema_diff.compare_schema', url_params);
}
self.model.set({
'source_ddl': undefined,
@ -305,7 +312,7 @@ export default class SchemaDiffUI {
// Format Schema object title with appropriate icon
var formatColumnTitle = function (row, cell, value, columnDef, dataContext) {
let icon = 'icon-' + dataContext.type;
return '<i class="ml-3 wcTabIcon '+ icon +'"></i><span>' + value + '</span>';
return '<i class="ml-2 wcTabIcon '+ icon +'"></i><span>' + value + '</span>';
};
// Grid Columns
@ -648,6 +655,30 @@ export default class SchemaDiffUI {
connect: function() {
self.connect_database(this.model.get('source_sid'), arguments[0], arguments[1]);
},
}, {
name: 'source_scid',
control: SchemaDiffSelect2Control,
group: 'source',
deps: ['source_sid', 'source_did'],
url: function() {
if (this.get('source_sid') && this.get('source_did'))
return url_for('schema_diff.schemas', {'sid': this.get('source_sid'), 'did': this.get('source_did')});
return false;
},
select2: {
allowClear: true,
placeholder: gettext('Select schema...'),
},
disabled: function(m) {
if (!_.isUndefined(m.get('source_did')) && !_.isNull(m.get('source_did'))
&& m.get('source_did') !== '') {
return false;
}
setTimeout(function() {
m.set('source_scid', undefined);
}, 10);
return true;
},
}, {
name: 'target_sid', label: false,
control: SchemaDiffSelect2Control,
@ -708,6 +739,30 @@ export default class SchemaDiffUI {
connect: function() {
self.connect_database(this.model.get('target_sid'), arguments[0], arguments[1]);
},
}, {
name: 'target_scid',
control: SchemaDiffSelect2Control,
group: 'target',
deps: ['target_sid', 'target_did'],
url: function() {
if (this.get('target_sid') && this.get('target_did'))
return url_for('schema_diff.schemas', {'sid': this.get('target_sid'), 'did': this.get('target_did')});
return false;
},
select2: {
allowClear: true,
placeholder: gettext('Select schema...'),
},
disabled: function(m) {
if (!_.isUndefined(m.get('target_did')) && !_.isNull(m.get('target_did'))
&& m.get('target_did') !== '') {
return false;
}
setTimeout(function() {
m.set('target_scid', undefined);
}, 10);
return true;
},
}],
});
@ -739,7 +794,9 @@ export default class SchemaDiffUI {
footer_panel.$container.find('#schema-diff-ddl-comp').append(self.footer.render().$el);
header_panel.$container.find('#schema-diff-grid').append(`<div class='obj_properties container-fluid'>
<div class='pg-panel-message'>` + gettext('Select the server and database for the source and target and click <strong>Compare</strong> to compare them.') + '</div></div>');
<div class='pg-panel-message'>` + gettext('<strong>Database Compare:</strong> Select the server and database for the source and target and Click <strong>Compare</strong>.') +
gettext('</br><strong>Schema Compare:</strong> Select the server, database and schema for the source and target and Click <strong>Compare</strong>.') +
gettext('</br><strong>Note:</strong> The dependencies will not be resolved in the Schema comparison.') + '</div></div>');
self.grid_width = $('#schema-diff-grid').width();
self.grid_height = this.panel_obj.height();

View File

@ -25,7 +25,7 @@ class SchemaDiffTestCase(BaseTestGenerator):
scenarios = [
# Fetching default URL for database node.
('Schema diff comparison', dict(
url='schema_diff/compare/{0}/{1}/{2}/{3}/{4}'))
url='schema_diff/compare_database/{0}/{1}/{2}/{3}/{4}'))
]
def setUp(self):