Added support to compare schemas and databases in schema diff. Fixes #5891
Before Width: | Height: | Size: 435 KiB After Width: | Height: | Size: 431 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 364 KiB After Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 247 KiB |
@ -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
|
||||
************
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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'],
|
||||
|
@ -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'],
|
||||
|
@ -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'],
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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',
|
||||
|
@ -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'],
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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();
|
||||
|
@ -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):
|
||||
|