Modified schema diff tool to compare two databases instead of two schemas. Fixes #5126
|
Before Width: | Height: | Size: 303 KiB After Width: | Height: | Size: 435 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 200 KiB |
|
Before Width: | Height: | Size: 295 KiB After Width: | Height: | Size: 364 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 302 KiB |
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 228 KiB |
@@ -10,6 +10,7 @@ New features
|
|||||||
************
|
************
|
||||||
|
|
||||||
| `Issue #3904 <https://redmine.postgresql.org/issues/3904>`_ - Replace charting library Flotr2 with ChartJS using React.
|
| `Issue #3904 <https://redmine.postgresql.org/issues/3904>`_ - Replace charting library Flotr2 with ChartJS using React.
|
||||||
|
| `Issue #5126 <https://redmine.postgresql.org/issues/5126>`_ - Modified schema diff tool to compare two databases instead of two schemas.
|
||||||
| `Issue #5610 <https://redmine.postgresql.org/issues/5610>`_ - Add a --yes command line option to setup-web.sh to allow non-interactive use.
|
| `Issue #5610 <https://redmine.postgresql.org/issues/5610>`_ - Add a --yes command line option to setup-web.sh to allow non-interactive use.
|
||||||
|
|
||||||
Housekeeping
|
Housekeeping
|
||||||
|
|||||||
@@ -4,29 +4,29 @@
|
|||||||
`Schema Diff`:index:
|
`Schema Diff`:index:
|
||||||
********************
|
********************
|
||||||
|
|
||||||
**Schema Diff** is a feature that allows you to compare schema objects between
|
**Schema Diff** is a feature that allows you to compare objects between
|
||||||
two database schemas. Use the *Tools* menu to access Schema Diff.
|
two databases. Use the *Tools* menu to access Schema Diff.
|
||||||
|
|
||||||
The Schema Diff feature allows you to:
|
The Schema Diff feature allows you to:
|
||||||
|
|
||||||
* Compare and synchronize the database schemas (from source to target).
|
* Compare and synchronize the database objects (from source to target).
|
||||||
|
|
||||||
* Visualize the differences between database schemas.
|
* Visualize the differences between database objects.
|
||||||
|
|
||||||
* List the differences in SQL statement for target schema objects.
|
* List the differences in SQL statement for target database objects.
|
||||||
|
|
||||||
* Generate synchronization scripts.
|
* Generate synchronization scripts.
|
||||||
|
|
||||||
|
|
||||||
**Note** - The source and target databases must be of the same major
|
**Note** - The source and target database servers must be of the same major
|
||||||
version.
|
version.
|
||||||
|
|
||||||
Click on *Schema Diff* under the *Tools* menu to open a selection panel. Choose
|
Click on *Schema Diff* under the *Tools* menu to open a selection panel. Choose
|
||||||
the source and target servers, databases, and schemas that will be
|
the source and target servers, and databases that will be
|
||||||
compared. After selecting the objects, click on the *Compare* button.
|
compared. After selecting the objects, click on the *Compare* button.
|
||||||
|
|
||||||
You can open multiple copies of *Schema Diff* in individual tabs
|
You can open multiple copies of *Schema Diff* in individual tabs
|
||||||
simultaneously. To close a copy of Schema Diff, click the *X* in the
|
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.
|
||||||
|
|
||||||
.. image:: images/schema_diff_dialog.png
|
.. image:: images/schema_diff_dialog.png
|
||||||
@@ -44,7 +44,7 @@ The Schema Diff Object Comparison Panel
|
|||||||
========================================
|
========================================
|
||||||
|
|
||||||
In the object comparison panel, you can select the source and target servers
|
In the object comparison panel, you can select the source and target servers
|
||||||
of the same major version, databases, and schemas to be compared. You can
|
of the same major version, and databases to be compared. You can
|
||||||
select any server listed under the browser tree whether it is connected or
|
select any server listed under the browser tree whether it is connected or
|
||||||
disconnected. If you select a server that is not connected then it will
|
disconnected. If you select a server that is not connected then it will
|
||||||
prompt you for the password before using the server.
|
prompt you for the password before using the server.
|
||||||
@@ -52,40 +52,36 @@ prompt you for the password before using the server.
|
|||||||
Next, select the databases that will be compared. The databases can be the
|
Next, select the databases that will be compared. The databases can be the
|
||||||
same or different (and within the same server or from different servers).
|
same or different (and within the same server or from different servers).
|
||||||
|
|
||||||
Lastly, select the source and target schemas which will be compared.
|
|
||||||
|
|
||||||
.. image:: images/schema_diff_compare_button.png
|
.. image:: images/schema_diff_compare_button.png
|
||||||
:alt: Schema diff compare button
|
:alt: Schema diff compare button
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
After you select servers, databases, and schemas, click on the
|
After you select servers, and databases, click on the
|
||||||
*Compare* button to obtain the *Comparison Result*.
|
*Compare* button to obtain the *Comparison Result*.
|
||||||
|
|
||||||
.. image:: images/schema_diff_comparison_results.png
|
.. image:: images/schema_diff_comparison_results.png
|
||||||
:alt: Schema diff comparison results
|
:alt: Schema diff comparison results
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Use the drop-down lists of Functions, Materialized Views, Tables,
|
Use the drop-down lists of Database Objects to view the DDL statements.
|
||||||
Trigger Functions, Procedures, and Views to view the DDL statements of
|
|
||||||
all the schema objects.
|
|
||||||
|
|
||||||
In the upper-right hand corner of the object comparison panel is a *Filter*
|
In the upper-right hand corner of the object comparison panel is a *Filter*
|
||||||
option that you can use to filter the schema objects based on the
|
option that you can use to filter the database objects based on the
|
||||||
following comparison criteria:
|
following comparison criteria:
|
||||||
|
|
||||||
* Identical – If the object is found in both schemas with the same SQL statement, then the comparison result is identical.
|
* Identical – If the object is found in both databases with the same SQL statement, then the comparison result is identical.
|
||||||
|
|
||||||
* Different – If the object is found in both schemas but have different SQL statements, then the comparison result is different.
|
* Different – If the object is found in both databases but have different SQL statements, then the comparison result is different.
|
||||||
|
|
||||||
* Source Only – If the object is found in source schema only and not in target schema, then the comparison result is source only.
|
* Source Only – If the object is found in source database only and not in target database, then the comparison result is source only.
|
||||||
|
|
||||||
* Target Only – If the object is found in target schema only and not in source schema, then the comparison result is target only.
|
* Target Only – If the object is found in target database only and not in source database, then the comparison result is target only.
|
||||||
|
|
||||||
.. image:: images/schema_diff_filter_option.png
|
.. image:: images/schema_diff_filter_option.png
|
||||||
:alt: Schema diff filter option
|
:alt: Schema diff filter option
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Click on any of the schema objects in the object comparison panel to
|
Click on any of the database objects in the object comparison panel to
|
||||||
display the DDL Statements of that object in the DDL Comparison panel.
|
display the DDL Statements of that object in the DDL Comparison panel.
|
||||||
|
|
||||||
|
|
||||||
@@ -94,36 +90,32 @@ Schema Diff DDL Comparison Panel
|
|||||||
|
|
||||||
The *DDL Comparison* panel displays three columns:
|
The *DDL Comparison* panel displays three columns:
|
||||||
|
|
||||||
* The first column displays the DDL statement of the object from the source schema.
|
* The first column displays the DDL statement of the object from the source database.
|
||||||
|
|
||||||
* The second column displays the DDL statement of the object from the target schema.
|
* The second column displays the DDL statement of the object from the target database.
|
||||||
|
|
||||||
* The third column displays the difference in the SQL statement of the target schema object.
|
* The third column displays the difference in the SQL statement of the target database object.
|
||||||
|
|
||||||
.. image:: images/schema_diff_DDL_comparison.png
|
.. image:: images/schema_diff_DDL_comparison.png
|
||||||
:alt: Schema diff DDL comparison
|
:alt: Schema diff DDL comparison
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
You can review the DDL statements of all the schema objects to
|
You can review the DDL statements of all the database objects to
|
||||||
check for the differences in the SQL statements.
|
check for the differences in the SQL statements.
|
||||||
|
|
||||||
Also, you can generate the SQL script of the differences found in the
|
Also, you can generate the SQL script of the differences found in the
|
||||||
target schema object based on the SQL statement of the source schema
|
target database object based on the SQL statement of the source database
|
||||||
object. To generate the script, select the checkboxes of the schema
|
object. To generate the script, select the checkboxes of the database
|
||||||
objects in the object comparison panel and then click on the *Generate Script*
|
objects in the object comparison panel and then click on the *Generate Script*
|
||||||
button in the upper-right hand corner of the object comparison panel.
|
button in the upper-right hand corner of the object comparison panel.
|
||||||
|
|
||||||
.. image:: images/schema_diff_generate_script.png
|
Select the database objects and click on the *Generate Script*
|
||||||
:alt: Schema diff generate script
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Select the schema objects and click on the *Generate Script*
|
|
||||||
button to open the *Query Tool* in a new tab, with the difference
|
button to open the *Query Tool* in a new tab, with the difference
|
||||||
in the SQL statement displayed in the *Query Editor*.
|
in the SQL statement displayed in the *Query Editor*.
|
||||||
|
|
||||||
If you have clicked on the schema object to check the difference
|
If you have clicked on the database object to check the difference
|
||||||
generated in the *DDL Comparison* Panel, and you have not selected the
|
generated in the *DDL Comparison* Panel, and you have not selected the
|
||||||
checkbox of the schema object, PEM will open the *Query Tool* in a new
|
checkbox of the database object, pgAdmin will open the *Query Tool* in a new
|
||||||
tab, with the differences in the SQL statements displayed in the *Query Editor*.
|
tab, with the differences in the SQL statements displayed in the *Query Editor*.
|
||||||
|
|
||||||
You can also use the *Copy* button to copy the difference generated in
|
You can also use the *Copy* button to copy the difference generated in
|
||||||
@@ -133,4 +125,4 @@ the *DDL Comparison* panel.
|
|||||||
:alt: Schema diff generate script query editor
|
:alt: Schema diff generate script query editor
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Apply the SQL Statement in the target schema to synchronize the schemas.
|
Apply the SQL Statement in the target database to synchronize the databases.
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
|||||||
make_response as ajax_response, gone
|
make_response as ajax_response, gone
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||||
|
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||||
|
|
||||||
|
|
||||||
class CastModule(CollectionNodeModule):
|
class CastModule(CollectionNodeModule):
|
||||||
@@ -88,7 +90,7 @@ class CastModule(CollectionNodeModule):
|
|||||||
blueprint = CastModule(__name__)
|
blueprint = CastModule(__name__)
|
||||||
|
|
||||||
|
|
||||||
class CastView(PGChildNodeView):
|
class CastView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||||
"""
|
"""
|
||||||
class CastView(PGChildNodeView)
|
class CastView(PGChildNodeView)
|
||||||
|
|
||||||
@@ -179,9 +181,12 @@ class CastView(PGChildNodeView):
|
|||||||
'get_functions': [
|
'get_functions': [
|
||||||
{'post': 'get_functions'},
|
{'post': 'get_functions'},
|
||||||
{'post': 'get_functions'}
|
{'post': 'get_functions'}
|
||||||
]
|
],
|
||||||
|
'compare': [{'get': 'compare'}, {'get': 'compare'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
keys_to_ignore = ['oid', 'id', 'oid-2']
|
||||||
|
|
||||||
def _init_(self, **kwargs):
|
def _init_(self, **kwargs):
|
||||||
self.conn = None
|
self.conn = None
|
||||||
self.template_path = None
|
self.template_path = None
|
||||||
@@ -318,26 +323,41 @@ class CastView(PGChildNodeView):
|
|||||||
:param cid: cast id
|
:param cid: cast id
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
status, res = self._fetch_properties(did, cid)
|
||||||
|
if not status:
|
||||||
|
return res
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def _fetch_properties(self, did, cid):
|
||||||
|
"""
|
||||||
|
This function fetch the properties of the
|
||||||
|
:param did:
|
||||||
|
:param cid:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
last_system_oid = 0 if self.blueprint.show_system_objects else \
|
||||||
|
self.datlastsysoid
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
||||||
cid=cid,
|
cid=cid,
|
||||||
datlastsysoid=self.datlastsysoid,
|
datlastsysoid=last_system_oid,
|
||||||
showsysobj=self.blueprint.show_system_objects
|
showsysobj=self.blueprint.show_system_objects
|
||||||
)
|
)
|
||||||
status, res = self.conn.execute_dict(sql)
|
status, res = self.conn.execute_dict(sql)
|
||||||
|
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return False, internal_server_error(errormsg=res)
|
||||||
|
|
||||||
if len(res['rows']) == 0:
|
if len(res['rows']) == 0:
|
||||||
return gone(
|
return False, gone(
|
||||||
gettext("Could not find the cast information.")
|
gettext("Could not find the cast information.")
|
||||||
)
|
)
|
||||||
|
|
||||||
return ajax_response(
|
return True, res['rows'][0]
|
||||||
response=res['rows'][0],
|
|
||||||
status=200
|
|
||||||
)
|
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def create(self, gid, sid, did):
|
def create(self, gid, sid, did):
|
||||||
@@ -436,29 +456,42 @@ class CastView(PGChildNodeView):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return internal_server_error(errormsg=str(e))
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_delete_data(cmd, cid, request_object):
|
||||||
|
"""
|
||||||
|
This function is used to get the data and cascade information.
|
||||||
|
:param cmd: Command
|
||||||
|
:param cid: Object ID
|
||||||
|
:param request_object: request object
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
cascade = False
|
||||||
|
# Below will decide if it's simple drop or drop with cascade call
|
||||||
|
if cmd == 'delete':
|
||||||
|
# This is a cascade operation
|
||||||
|
cascade = True
|
||||||
|
|
||||||
|
if cid is None:
|
||||||
|
data = request_object.form if request_object.form else \
|
||||||
|
json.loads(request_object.data, encoding='utf-8')
|
||||||
|
else:
|
||||||
|
data = {'ids': [cid]}
|
||||||
|
|
||||||
|
return cascade, data
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def delete(self, gid, sid, did, cid=None):
|
def delete(self, gid, sid, did, cid=None, only_sql=False):
|
||||||
"""
|
"""
|
||||||
This function will drop the cast object
|
This function will drop the cast object
|
||||||
:param cid: cast id
|
:param cid: cast id
|
||||||
:param did: database id
|
:param did: database id
|
||||||
:param sid: server id
|
:param sid: server id
|
||||||
:param gid: group id
|
:param gid: group id
|
||||||
|
:param only_sql:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
# Below will decide if it's simple drop or drop with cascade call
|
# get the value of cascade and data
|
||||||
if self.cmd == 'delete':
|
cascade, data = self.get_delete_data(self.cmd, cid, request)
|
||||||
# This is a cascade operation
|
|
||||||
cascade = True
|
|
||||||
else:
|
|
||||||
cascade = False
|
|
||||||
|
|
||||||
if cid is None:
|
|
||||||
data = request.form if request.form else json.loads(
|
|
||||||
request.data, encoding='utf-8'
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
data = {'ids': [cid]}
|
|
||||||
|
|
||||||
for cid in data['ids']:
|
for cid in data['ids']:
|
||||||
try:
|
try:
|
||||||
@@ -490,6 +523,11 @@ class CastView(PGChildNodeView):
|
|||||||
casttarget=result['casttarget'],
|
casttarget=result['casttarget'],
|
||||||
cascade=cascade
|
cascade=cascade
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Used for schema diff tool
|
||||||
|
if only_sql:
|
||||||
|
return sql
|
||||||
|
|
||||||
status, res = self.conn.execute_scalar(sql)
|
status, res = self.conn.execute_scalar(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
@@ -638,13 +676,14 @@ class CastView(PGChildNodeView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def sql(self, gid, sid, did, cid):
|
def sql(self, gid, sid, did, cid, json_resp=True):
|
||||||
"""
|
"""
|
||||||
This function will generate sql for sql panel
|
This function will generate sql for sql panel
|
||||||
:param gid: group id
|
:param gid: group id
|
||||||
:param sid: server id
|
:param sid: server id
|
||||||
:param did: database id
|
:param did: database id
|
||||||
:param cid: cast id
|
:param cid: cast id
|
||||||
|
:param json_resp:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
@@ -653,6 +692,7 @@ class CastView(PGChildNodeView):
|
|||||||
cid=cid,
|
cid=cid,
|
||||||
conn=self.conn
|
conn=self.conn
|
||||||
)
|
)
|
||||||
|
|
||||||
status, res = self.conn.execute_scalar(sql)
|
status, res = self.conn.execute_scalar(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(gettext(
|
return internal_server_error(gettext(
|
||||||
@@ -665,6 +705,9 @@ class CastView(PGChildNodeView):
|
|||||||
"cast node."
|
"cast node."
|
||||||
))
|
))
|
||||||
|
|
||||||
|
if not json_resp:
|
||||||
|
return res
|
||||||
|
|
||||||
return ajax_response(response=res)
|
return ajax_response(response=res)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -706,5 +749,63 @@ class CastView(PGChildNodeView):
|
|||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@check_precondition
|
||||||
|
def fetch_objects_to_compare(self, sid, did):
|
||||||
|
"""
|
||||||
|
This function will fetch the list of all the casts for
|
||||||
|
specified database id.
|
||||||
|
|
||||||
|
:param sid: Server Id
|
||||||
|
:param did: Database Id
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
res = dict()
|
||||||
|
|
||||||
|
last_system_oid = 0
|
||||||
|
if self.manager.db_info is not None and did in self.manager.db_info:
|
||||||
|
last_system_oid = (self.manager.db_info[did])['datlastsysoid']
|
||||||
|
|
||||||
|
sql = render_template(
|
||||||
|
"/".join([self.template_path, 'nodes.sql']),
|
||||||
|
datlastsysoid=last_system_oid,
|
||||||
|
showsysobj=self.blueprint.show_system_objects
|
||||||
|
)
|
||||||
|
status, rset = self.conn.execute_2darray(sql)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=rset)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
status, data = self._fetch_properties(did, row['oid'])
|
||||||
|
if status:
|
||||||
|
res[row['name']] = data
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_sql_from_diff(self, **kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to get the DDL/DML statements.
|
||||||
|
:param kwargs:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
gid = kwargs.get('gid')
|
||||||
|
sid = kwargs.get('sid')
|
||||||
|
did = kwargs.get('did')
|
||||||
|
oid = kwargs.get('oid')
|
||||||
|
data = kwargs.get('data', None)
|
||||||
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
sql, name = self.get_sql(gid=gid, sid=sid, did=did, data=data,
|
||||||
|
cid=oid)
|
||||||
|
else:
|
||||||
|
if drop_sql:
|
||||||
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
|
cid=oid, only_sql=True)
|
||||||
|
else:
|
||||||
|
sql = self.sql(gid=gid, sid=sid, did=did, cid=oid,
|
||||||
|
json_resp=False)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
SchemaDiffRegistry(blueprint.node_type, CastView, 'Database')
|
||||||
CastView.register_node_view(blueprint)
|
CastView.register_node_view(blueprint)
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
|||||||
make_response as ajax_response, gone
|
make_response as ajax_response, gone
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||||
|
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||||
|
|
||||||
|
|
||||||
class EventTriggerModule(CollectionNodeModule):
|
class EventTriggerModule(CollectionNodeModule):
|
||||||
@@ -94,7 +96,7 @@ class EventTriggerModule(CollectionNodeModule):
|
|||||||
blueprint = EventTriggerModule(__name__)
|
blueprint = EventTriggerModule(__name__)
|
||||||
|
|
||||||
|
|
||||||
class EventTriggerView(PGChildNodeView):
|
class EventTriggerView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||||
"""
|
"""
|
||||||
class EventTriggerView(PGChildNodeView)
|
class EventTriggerView(PGChildNodeView)
|
||||||
|
|
||||||
@@ -172,6 +174,8 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
'fopts': [{'get': 'get_event_funcs'}, {'get': 'get_event_funcs'}]
|
'fopts': [{'get': 'get_event_funcs'}, {'get': 'get_event_funcs'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
keys_to_ignore = ['oid', 'xmin', 'oid-2', 'eventfuncoid']
|
||||||
|
|
||||||
def check_precondition(f):
|
def check_precondition(f):
|
||||||
"""
|
"""
|
||||||
This function will behave as a decorator which will checks
|
This function will behave as a decorator which will checks
|
||||||
@@ -325,6 +329,22 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
status, res = self._fetch_properties(did, etid)
|
||||||
|
if not status:
|
||||||
|
return res
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def _fetch_properties(self, did, etid):
|
||||||
|
"""
|
||||||
|
This function fetch the properties of the event trigger.
|
||||||
|
:param did:
|
||||||
|
:param etid:
|
||||||
|
:return:
|
||||||
"""
|
"""
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
||||||
@@ -332,21 +352,17 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
)
|
)
|
||||||
status, res = self.conn.execute_dict(sql)
|
status, res = self.conn.execute_dict(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return False, internal_server_error(errormsg=res)
|
||||||
|
|
||||||
if len(res['rows']) == 0:
|
if len(res['rows']) == 0:
|
||||||
return gone(
|
return False, gone(
|
||||||
gettext("Could not find the event trigger information.")
|
gettext("Could not find the event trigger information."))
|
||||||
)
|
|
||||||
|
|
||||||
result = res['rows'][0]
|
result = res['rows'][0]
|
||||||
result['is_sys_obj'] = (result['oid'] <= self.datlastsysoid)
|
result['is_sys_obj'] = (result['oid'] <= self.datlastsysoid)
|
||||||
result = self._formatter(result)
|
result = self._formatter(result)
|
||||||
|
|
||||||
return ajax_response(
|
return True, result
|
||||||
response=result,
|
|
||||||
status=200
|
|
||||||
)
|
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def create(self, gid, sid, did):
|
def create(self, gid, sid, did):
|
||||||
@@ -445,7 +461,7 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
# Most probably this is due to error
|
# Most probably this is due to error
|
||||||
if not isinstance(sql, str):
|
if not isinstance(sql, str):
|
||||||
return sql
|
return sql
|
||||||
sql = sql.strip('\n').strip(' ')
|
|
||||||
if sql != "":
|
if sql != "":
|
||||||
status, res = self.conn.execute_scalar(sql)
|
status, res = self.conn.execute_scalar(sql)
|
||||||
if not status:
|
if not status:
|
||||||
@@ -480,8 +496,31 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return internal_server_error(errormsg=str(e))
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_delete_data(cmd, etid, request_object):
|
||||||
|
"""
|
||||||
|
This function is used to get the data and cascade information.
|
||||||
|
:param cmd: Command
|
||||||
|
:param etid: Object ID
|
||||||
|
:param request_object: request object
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
cascade = False
|
||||||
|
# Below will decide if it's simple drop or drop with cascade call
|
||||||
|
if cmd == 'delete':
|
||||||
|
# This is a cascade operation
|
||||||
|
cascade = True
|
||||||
|
|
||||||
|
if etid is None:
|
||||||
|
data = request_object.form if request_object.form else \
|
||||||
|
json.loads(request_object.data, encoding='utf-8')
|
||||||
|
else:
|
||||||
|
data = {'ids': [etid]}
|
||||||
|
|
||||||
|
return cascade, data
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def delete(self, gid, sid, did, etid=None):
|
def delete(self, gid, sid, did, etid=None, only_sql=False):
|
||||||
"""
|
"""
|
||||||
This function will delete an existing event trigger object.
|
This function will delete an existing event trigger object.
|
||||||
|
|
||||||
@@ -490,23 +529,13 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
sid: Server ID
|
sid: Server ID
|
||||||
did: Database ID
|
did: Database ID
|
||||||
etid: Event trigger ID
|
etid: Event trigger ID
|
||||||
|
only_sql:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# get the value of cascade and data
|
||||||
if self.cmd == 'delete':
|
cascade, data = self.get_delete_data(self.cmd, etid, request)
|
||||||
# This is a cascade operation
|
|
||||||
cascade = True
|
|
||||||
else:
|
|
||||||
cascade = False
|
|
||||||
|
|
||||||
if etid is None:
|
|
||||||
data = request.form if request.form else json.loads(
|
|
||||||
request.data, encoding='utf-8'
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
data = {'ids': [etid]}
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for etid in data['ids']:
|
for etid in data['ids']:
|
||||||
@@ -534,6 +563,11 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
"/".join([self.template_path, self._DELETE_SQL]),
|
"/".join([self.template_path, self._DELETE_SQL]),
|
||||||
name=name, cascade=cascade
|
name=name, cascade=cascade
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Used for schema diff tool
|
||||||
|
if only_sql:
|
||||||
|
return sql
|
||||||
|
|
||||||
status, res = self.conn.execute_scalar(sql)
|
status, res = self.conn.execute_scalar(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
@@ -572,7 +606,7 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
# Most probably this is due to error
|
# Most probably this is due to error
|
||||||
if not isinstance(sql, str):
|
if not isinstance(sql, str):
|
||||||
return sql
|
return sql
|
||||||
sql = sql.strip('\n').strip(' ')
|
|
||||||
sql = re.sub('\n{2,}', '\n\n', sql)
|
sql = re.sub('\n{2,}', '\n\n', sql)
|
||||||
if sql == '':
|
if sql == '':
|
||||||
sql = "--modified SQL"
|
sql = "--modified SQL"
|
||||||
@@ -657,10 +691,10 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
"/".join([self.template_path, self._GRANT_SQL]),
|
"/".join([self.template_path, self._GRANT_SQL]),
|
||||||
data=data
|
data=data
|
||||||
)
|
)
|
||||||
return sql
|
return sql.strip('\n').strip(' ')
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def sql(self, gid, sid, did, etid):
|
def sql(self, gid, sid, did, etid, json_resp=True):
|
||||||
"""
|
"""
|
||||||
This function will generate sql to show in the sql pane for the
|
This function will generate sql to show in the sql pane for the
|
||||||
selected event trigger node.
|
selected event trigger node.
|
||||||
@@ -670,6 +704,7 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
sid: Server ID
|
sid: Server ID
|
||||||
did: Database ID
|
did: Database ID
|
||||||
etid: Event trigger ID
|
etid: Event trigger ID
|
||||||
|
json_resp:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
@@ -722,6 +757,9 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
sql = sql_header + sql
|
sql = sql_header + sql
|
||||||
sql = re.sub('\n{2,}', '\n\n', sql)
|
sql = re.sub('\n{2,}', '\n\n', sql)
|
||||||
|
|
||||||
|
if not json_resp:
|
||||||
|
return sql
|
||||||
|
|
||||||
return ajax_response(response=sql)
|
return ajax_response(response=sql)
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
@@ -791,5 +829,62 @@ class EventTriggerView(PGChildNodeView):
|
|||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@check_precondition
|
||||||
|
def fetch_objects_to_compare(self, sid, did):
|
||||||
|
"""
|
||||||
|
This function will fetch the list of all the event triggers for
|
||||||
|
specified database id.
|
||||||
|
|
||||||
|
:param sid: Server Id
|
||||||
|
:param did: Database Id
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
res = dict()
|
||||||
|
|
||||||
|
last_system_oid = 0
|
||||||
|
if self.manager.db_info is not None and did in self.manager.db_info:
|
||||||
|
last_system_oid = (self.manager.db_info[did])['datlastsysoid']
|
||||||
|
|
||||||
|
sql = render_template(
|
||||||
|
"/".join([self.template_path, 'nodes.sql']),
|
||||||
|
datlastsysoid=last_system_oid,
|
||||||
|
showsysobj=self.blueprint.show_system_objects
|
||||||
|
)
|
||||||
|
status, rset = self.conn.execute_2darray(sql)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=rset)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
status, data = self._fetch_properties(did, row['oid'])
|
||||||
|
if status:
|
||||||
|
res[row['name']] = data
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_sql_from_diff(self, **kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to get the DDL/DML statements.
|
||||||
|
:param kwargs:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
gid = kwargs.get('gid')
|
||||||
|
sid = kwargs.get('sid')
|
||||||
|
did = kwargs.get('did')
|
||||||
|
oid = kwargs.get('oid')
|
||||||
|
data = kwargs.get('data', None)
|
||||||
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
sql = self.get_sql(data=data, etid=oid)
|
||||||
|
else:
|
||||||
|
if drop_sql:
|
||||||
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
|
etid=oid, only_sql=True)
|
||||||
|
else:
|
||||||
|
sql = self.sql(gid=gid, sid=sid, did=did, etid=oid,
|
||||||
|
json_resp=False)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
SchemaDiffRegistry(blueprint.node_type, EventTriggerView, 'Database')
|
||||||
EventTriggerView.register_node_view(blueprint)
|
EventTriggerView.register_node_view(blueprint)
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
{% if (data.eventfunname and data.eventfunname != o_data.eventfunname) or
|
{% if (data.eventfunname and data.eventfunname != o_data.eventfunname) or
|
||||||
(data.eventname and data.eventname != o_data.eventname) or
|
(data.eventname and data.eventname != o_data.eventname) or
|
||||||
(data.when and data.when != o_data.when) %}
|
(data.when and data.when != o_data.when) %}
|
||||||
|
-- WARNING:
|
||||||
|
-- We have found the difference in either of Trigger Function, Event or WHEN
|
||||||
|
-- so we need to drop the existing event trigger first and re-create it.
|
||||||
DROP EVENT TRIGGER IF EXISTS {{ conn|qtIdent(o_data.name) }};
|
DROP EVENT TRIGGER IF EXISTS {{ conn|qtIdent(o_data.name) }};
|
||||||
|
|
||||||
CREATE EVENT TRIGGER {{ conn|qtIdent(data.name) if data.name else conn|qtIdent(o_data.name) }} ON {{ data.eventname if data.eventname else o_data.eventname }}
|
CREATE EVENT TRIGGER {{ conn|qtIdent(data.name) if data.name else conn|qtIdent(o_data.name) }} ON {{ data.eventname if data.eventname else o_data.eventname }}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ from pgadmin.utils.ajax import make_json_response, \
|
|||||||
make_response as ajax_response, internal_server_error, gone
|
make_response as ajax_response, internal_server_error, gone
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||||
|
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||||
|
|
||||||
|
|
||||||
class ExtensionModule(CollectionNodeModule):
|
class ExtensionModule(CollectionNodeModule):
|
||||||
@@ -75,7 +77,7 @@ class ExtensionModule(CollectionNodeModule):
|
|||||||
blueprint = ExtensionModule(__name__)
|
blueprint = ExtensionModule(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ExtensionView(PGChildNodeView):
|
class ExtensionView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||||
"""
|
"""
|
||||||
This is a class for extension nodes which inherits the
|
This is a class for extension nodes which inherits the
|
||||||
properties and methods from NodeView class and define
|
properties and methods from NodeView class and define
|
||||||
@@ -173,7 +175,7 @@ class ExtensionView(PGChildNodeView):
|
|||||||
for row in rset['rows']:
|
for row in rset['rows']:
|
||||||
res.append(
|
res.append(
|
||||||
self.blueprint.generate_browser_node(
|
self.blueprint.generate_browser_node(
|
||||||
row['eid'],
|
row['oid'],
|
||||||
did,
|
did,
|
||||||
row['name'],
|
row['name'],
|
||||||
'icon-extension'
|
'icon-extension'
|
||||||
@@ -199,7 +201,7 @@ class ExtensionView(PGChildNodeView):
|
|||||||
for row in rset['rows']:
|
for row in rset['rows']:
|
||||||
return make_json_response(
|
return make_json_response(
|
||||||
data=self.blueprint.generate_browser_node(
|
data=self.blueprint.generate_browser_node(
|
||||||
row['eid'],
|
row['oid'],
|
||||||
did,
|
did,
|
||||||
row['name'],
|
row['name'],
|
||||||
'icon-extension'
|
'icon-extension'
|
||||||
@@ -214,23 +216,37 @@ class ExtensionView(PGChildNodeView):
|
|||||||
"""
|
"""
|
||||||
Fetch the properties of a single extension and render in properties tab
|
Fetch the properties of a single extension and render in properties tab
|
||||||
"""
|
"""
|
||||||
|
status, res = self._fetch_properties(did, eid)
|
||||||
|
if not status:
|
||||||
|
return res
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def _fetch_properties(self, did, eid):
|
||||||
|
"""
|
||||||
|
This function fetch the properties of the extension.
|
||||||
|
:param did:
|
||||||
|
:param eid:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
SQL = render_template("/".join(
|
SQL = render_template("/".join(
|
||||||
[self.template_path, self._PROPERTIES_SQL]), eid=eid)
|
[self.template_path, self._PROPERTIES_SQL]), eid=eid)
|
||||||
status, res = self.conn.execute_dict(SQL)
|
status, res = self.conn.execute_dict(SQL)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return False, internal_server_error(errormsg=res)
|
||||||
|
|
||||||
if len(res['rows']) == 0:
|
if len(res['rows']) == 0:
|
||||||
return gone(
|
return False, gone(
|
||||||
gettext("Could not find the extension information.")
|
gettext("Could not find the extension information.")
|
||||||
)
|
)
|
||||||
|
|
||||||
res['rows'][0]['is_sys_obj'] = (
|
res['rows'][0]['is_sys_obj'] = (
|
||||||
res['rows'][0]['eid'] <= self.datlastsysoid)
|
res['rows'][0]['oid'] <= self.datlastsysoid)
|
||||||
return ajax_response(
|
|
||||||
response=res['rows'][0],
|
return True, res['rows'][0]
|
||||||
status=200
|
|
||||||
)
|
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def create(self, gid, sid, did):
|
def create(self, gid, sid, did):
|
||||||
@@ -278,7 +294,7 @@ class ExtensionView(PGChildNodeView):
|
|||||||
for row in rset['rows']:
|
for row in rset['rows']:
|
||||||
return jsonify(
|
return jsonify(
|
||||||
node=self.blueprint.generate_browser_node(
|
node=self.blueprint.generate_browser_node(
|
||||||
row['eid'],
|
row['oid'],
|
||||||
did,
|
did,
|
||||||
row['name'],
|
row['name'],
|
||||||
'icon-extension'
|
'icon-extension'
|
||||||
@@ -316,7 +332,7 @@ class ExtensionView(PGChildNodeView):
|
|||||||
return internal_server_error(errormsg=str(e))
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def delete(self, gid, sid, did, eid=None):
|
def delete(self, gid, sid, did, eid=None, only_sql=False):
|
||||||
"""
|
"""
|
||||||
This function will drop/drop cascade a extension object
|
This function will drop/drop cascade a extension object
|
||||||
"""
|
"""
|
||||||
@@ -355,6 +371,11 @@ class ExtensionView(PGChildNodeView):
|
|||||||
SQL = render_template("/".join(
|
SQL = render_template("/".join(
|
||||||
[self.template_path, self._DELETE_SQL]
|
[self.template_path, self._DELETE_SQL]
|
||||||
), name=name, cascade=cascade)
|
), name=name, cascade=cascade)
|
||||||
|
|
||||||
|
# Used for schema diff tool
|
||||||
|
if only_sql:
|
||||||
|
return SQL
|
||||||
|
|
||||||
status, res = self.conn.execute_scalar(SQL)
|
status, res = self.conn.execute_scalar(SQL)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
@@ -452,7 +473,7 @@ class ExtensionView(PGChildNodeView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def sql(self, gid, sid, did, eid):
|
def sql(self, gid, sid, did, eid, json_resp=True):
|
||||||
"""
|
"""
|
||||||
This function will generate sql for the sql panel
|
This function will generate sql for the sql panel
|
||||||
"""
|
"""
|
||||||
@@ -477,6 +498,9 @@ class ExtensionView(PGChildNodeView):
|
|||||||
display_comments=True
|
display_comments=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not json_resp:
|
||||||
|
return SQL
|
||||||
|
|
||||||
return ajax_response(response=SQL)
|
return ajax_response(response=SQL)
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
@@ -515,6 +539,57 @@ class ExtensionView(PGChildNodeView):
|
|||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@check_precondition
|
||||||
|
def fetch_objects_to_compare(self, sid, did):
|
||||||
|
"""
|
||||||
|
This function will fetch the list of all the extensions for
|
||||||
|
specified database id.
|
||||||
|
|
||||||
|
:param sid: Server Id
|
||||||
|
:param did: Database Id
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
res = dict()
|
||||||
|
|
||||||
|
sql = render_template("/".join([self.template_path,
|
||||||
|
'properties.sql']))
|
||||||
|
status, rset = self.conn.execute_2darray(sql)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=rset)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
status, data = self._fetch_properties(did, row['oid'])
|
||||||
|
if status:
|
||||||
|
res[row['name']] = data
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_sql_from_diff(self, **kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to get the DDL/DML statements.
|
||||||
|
:param kwargs
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
gid = kwargs.get('gid')
|
||||||
|
sid = kwargs.get('sid')
|
||||||
|
did = kwargs.get('did')
|
||||||
|
oid = kwargs.get('oid')
|
||||||
|
data = kwargs.get('data', None)
|
||||||
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
sql, name = self.getSQL(gid=gid, sid=sid, did=did, data=data,
|
||||||
|
eid=oid)
|
||||||
|
else:
|
||||||
|
if drop_sql:
|
||||||
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
|
eid=oid, only_sql=True)
|
||||||
|
else:
|
||||||
|
sql = self.sql(gid=gid, sid=sid, did=did, eid=oid,
|
||||||
|
json_resp=False)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
SchemaDiffRegistry(blueprint.node_type, ExtensionView, 'Database')
|
||||||
# Register and add ExtensionView as blueprint
|
# Register and add ExtensionView as blueprint
|
||||||
ExtensionView.register_node_view(blueprint)
|
ExtensionView.register_node_view(blueprint)
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ SELECT x.extname from pg_extension x
|
|||||||
WHERE x.oid = {{ eid }}::oid
|
WHERE x.oid = {{ eid }}::oid
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if name %}
|
{% if name %}
|
||||||
DROP EXTENSION {{ conn|qtIdent(name) }} {% if cascade %} CASCADE {% endif %}
|
DROP EXTENSION {{ conn|qtIdent(name) }}{% if cascade %} CASCADE{% endif %};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{#===================Fetch properties of each extension by name or oid===================#}
|
{#===================Fetch properties of each extension by name or oid===================#}
|
||||||
SELECT
|
SELECT
|
||||||
x.oid AS eid, pg_get_userbyid(extowner) AS owner,
|
x.oid, pg_get_userbyid(extowner) AS owner,
|
||||||
x.extname AS name, n.nspname AS schema,
|
x.extname AS name, n.nspname AS schema,
|
||||||
x.extrelocatable AS relocatable, x.extversion AS version,
|
x.extrelocatable AS relocatable, x.extversion AS version,
|
||||||
e.comment
|
e.comment
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
|||||||
make_response as ajax_response, gone
|
make_response as ajax_response, gone
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||||
|
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||||
|
|
||||||
|
|
||||||
class ForeignDataWrapperModule(CollectionNodeModule):
|
class ForeignDataWrapperModule(CollectionNodeModule):
|
||||||
@@ -98,7 +100,7 @@ class ForeignDataWrapperModule(CollectionNodeModule):
|
|||||||
blueprint = ForeignDataWrapperModule(__name__)
|
blueprint = ForeignDataWrapperModule(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ForeignDataWrapperView(PGChildNodeView):
|
class ForeignDataWrapperView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||||
"""
|
"""
|
||||||
class ForeignDataWrapperView(PGChildNodeView)
|
class ForeignDataWrapperView(PGChildNodeView)
|
||||||
|
|
||||||
@@ -196,6 +198,8 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
'get_validators': [{}, {'get': 'get_validators'}]
|
'get_validators': [{}, {'get': 'get_validators'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
keys_to_ignore = ['oid', 'oid-2', 'fdwhandler', 'fdwvalidator']
|
||||||
|
|
||||||
def check_precondition(f):
|
def check_precondition(f):
|
||||||
"""
|
"""
|
||||||
This function will behave as a decorator which will checks
|
This function will behave as a decorator which will checks
|
||||||
@@ -280,7 +284,7 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
for row in r_set['rows']:
|
for row in r_set['rows']:
|
||||||
res.append(
|
res.append(
|
||||||
self.blueprint.generate_browser_node(
|
self.blueprint.generate_browser_node(
|
||||||
row['fdwoid'],
|
row['oid'],
|
||||||
did,
|
did,
|
||||||
row['name'],
|
row['name'],
|
||||||
icon="icon-foreign_data_wrapper"
|
icon="icon-foreign_data_wrapper"
|
||||||
@@ -312,7 +316,7 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
for row in r_set['rows']:
|
for row in r_set['rows']:
|
||||||
return make_json_response(
|
return make_json_response(
|
||||||
data=self.blueprint.generate_browser_node(
|
data=self.blueprint.generate_browser_node(
|
||||||
row['fdwoid'],
|
row['oid'],
|
||||||
did,
|
did,
|
||||||
row['name'],
|
row['name'],
|
||||||
icon="icon-foreign_data_wrapper"
|
icon="icon-foreign_data_wrapper"
|
||||||
@@ -335,23 +339,40 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
fid: foreign data wrapper ID
|
fid: foreign data wrapper ID
|
||||||
"""
|
"""
|
||||||
|
status, res = self._fetch_properties(fid)
|
||||||
|
if not status:
|
||||||
|
return res
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def _fetch_properties(self, fid):
|
||||||
|
"""
|
||||||
|
This function fetch the properties of the FDW.
|
||||||
|
:param fid:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
sql = render_template("/".join([self.template_path,
|
sql = render_template("/".join([self.template_path,
|
||||||
self._PROPERTIES_SQL]),
|
self._PROPERTIES_SQL]),
|
||||||
fid=fid, conn=self.conn
|
fid=fid, conn=self.conn
|
||||||
)
|
)
|
||||||
status, res = self.conn.execute_dict(sql)
|
status, res = self.conn.execute_dict(sql)
|
||||||
|
|
||||||
|
status, res = self.conn.execute_dict(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return False, internal_server_error(errormsg=res)
|
||||||
|
|
||||||
if len(res['rows']) == 0:
|
if len(res['rows']) == 0:
|
||||||
return gone(
|
return False, gone(
|
||||||
gettext("Could not find the foreign data"
|
gettext("Could not find the foreign data"
|
||||||
" wrapper information.")
|
" wrapper information.")
|
||||||
)
|
)
|
||||||
|
|
||||||
res['rows'][0]['is_sys_obj'] = (
|
res['rows'][0]['is_sys_obj'] = (
|
||||||
res['rows'][0]['fdwoid'] <= self.datlastsysoid)
|
res['rows'][0]['oid'] <= self.datlastsysoid)
|
||||||
|
|
||||||
if res['rows'][0]['fdwoptions'] is not None:
|
if res['rows'][0]['fdwoptions'] is not None:
|
||||||
res['rows'][0]['fdwoptions'] = tokenize_options(
|
res['rows'][0]['fdwoptions'] = tokenize_options(
|
||||||
@@ -362,9 +383,10 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
sql = render_template("/".join([self.template_path, self._ACL_SQL]),
|
sql = render_template("/".join([self.template_path, self._ACL_SQL]),
|
||||||
fid=fid
|
fid=fid
|
||||||
)
|
)
|
||||||
|
|
||||||
status, fdw_acl_res = self.conn.execute_dict(sql)
|
status, fdw_acl_res = self.conn.execute_dict(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=fdw_acl_res)
|
return False, internal_server_error(errormsg=fdw_acl_res)
|
||||||
|
|
||||||
for row in fdw_acl_res['rows']:
|
for row in fdw_acl_res['rows']:
|
||||||
privilege = parse_priv_from_db(row)
|
privilege = parse_priv_from_db(row)
|
||||||
@@ -373,10 +395,7 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
else:
|
else:
|
||||||
res['rows'][0][row['deftype']] = [privilege]
|
res['rows'][0][row['deftype']] = [privilege]
|
||||||
|
|
||||||
return ajax_response(
|
return True, res['rows'][0]
|
||||||
response=res['rows'][0],
|
|
||||||
status=200
|
|
||||||
)
|
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def create(self, gid, sid, did):
|
def create(self, gid, sid, did):
|
||||||
@@ -438,7 +457,7 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
for row in r_set['rows']:
|
for row in r_set['rows']:
|
||||||
return jsonify(
|
return jsonify(
|
||||||
node=self.blueprint.generate_browser_node(
|
node=self.blueprint.generate_browser_node(
|
||||||
row['fdwoid'],
|
row['oid'],
|
||||||
did,
|
did,
|
||||||
row['name'],
|
row['name'],
|
||||||
icon='icon-foreign_data_wrapper'
|
icon='icon-foreign_data_wrapper'
|
||||||
@@ -484,8 +503,31 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return internal_server_error(errormsg=str(e))
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_delete_data(cmd, fid, request_object):
|
||||||
|
"""
|
||||||
|
This function is used to get the data and cascade information.
|
||||||
|
:param cmd: Command
|
||||||
|
:param fid: Object ID
|
||||||
|
:param request_object: request object
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
cascade = False
|
||||||
|
# Below will decide if it's simple drop or drop with cascade call
|
||||||
|
if cmd == 'delete':
|
||||||
|
# This is a cascade operation
|
||||||
|
cascade = True
|
||||||
|
|
||||||
|
if fid is None:
|
||||||
|
data = request_object.form if request_object.form else \
|
||||||
|
json.loads(request_object.data, encoding='utf-8')
|
||||||
|
else:
|
||||||
|
data = {'ids': [fid]}
|
||||||
|
|
||||||
|
return cascade, data
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def delete(self, gid, sid, did, fid=None):
|
def delete(self, gid, sid, did, fid=None, only_sql=False):
|
||||||
"""
|
"""
|
||||||
This function will delete the selected foreign data wrapper node.
|
This function will delete the selected foreign data wrapper node.
|
||||||
|
|
||||||
@@ -494,19 +536,10 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
sid: Server ID
|
sid: Server ID
|
||||||
did: Database ID
|
did: Database ID
|
||||||
fid: foreign data wrapper ID
|
fid: foreign data wrapper ID
|
||||||
|
only_sql:
|
||||||
"""
|
"""
|
||||||
if fid is None:
|
# get the value of cascade and data
|
||||||
data = request.form if request.form else json.loads(
|
cascade, data = self.get_delete_data(self.cmd, fid, request)
|
||||||
request.data, encoding='utf-8'
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
data = {'ids': [fid]}
|
|
||||||
|
|
||||||
if self.cmd == 'delete':
|
|
||||||
# This is a cascade operation
|
|
||||||
cascade = True
|
|
||||||
else:
|
|
||||||
cascade = False
|
|
||||||
|
|
||||||
for fid in data['ids']:
|
for fid in data['ids']:
|
||||||
try:
|
try:
|
||||||
@@ -537,6 +570,11 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
name=name,
|
name=name,
|
||||||
cascade=cascade,
|
cascade=cascade,
|
||||||
conn=self.conn)
|
conn=self.conn)
|
||||||
|
|
||||||
|
# Used for schema diff tool
|
||||||
|
if only_sql:
|
||||||
|
return sql
|
||||||
|
|
||||||
status, res = self.conn.execute_scalar(sql)
|
status, res = self.conn.execute_scalar(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
@@ -717,14 +755,15 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
is_valid_changed_options=is_valid_changed_options,
|
is_valid_changed_options=is_valid_changed_options,
|
||||||
conn=self.conn
|
conn=self.conn
|
||||||
)
|
)
|
||||||
return sql, data['name'] if 'name' in data else old_data['name']
|
return sql.strip('\n'), \
|
||||||
|
data['name'] if 'name' in data else old_data['name']
|
||||||
else:
|
else:
|
||||||
sql = self._get_create_sql(data)
|
sql = self._get_create_sql(data)
|
||||||
|
|
||||||
return sql, data['name']
|
return sql.strip('\n'), data['name']
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def sql(self, gid, sid, did, fid):
|
def sql(self, gid, sid, did, fid, json_resp=True):
|
||||||
"""
|
"""
|
||||||
This function will generate sql to show it in sql pane
|
This function will generate sql to show it in sql pane
|
||||||
for the selected foreign data wrapper node.
|
for the selected foreign data wrapper node.
|
||||||
@@ -734,6 +773,7 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
sid: Server ID
|
sid: Server ID
|
||||||
did: Database ID
|
did: Database ID
|
||||||
fid: Foreign data wrapper ID
|
fid: Foreign data wrapper ID
|
||||||
|
json_resp:
|
||||||
"""
|
"""
|
||||||
sql = render_template("/".join([self.template_path,
|
sql = render_template("/".join([self.template_path,
|
||||||
self._PROPERTIES_SQL]),
|
self._PROPERTIES_SQL]),
|
||||||
@@ -795,6 +835,9 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
|
|
||||||
sql = sql_header + sql
|
sql = sql_header + sql
|
||||||
|
|
||||||
|
if not json_resp:
|
||||||
|
return sql.strip('\n')
|
||||||
|
|
||||||
return ajax_response(response=sql.strip('\n'))
|
return ajax_response(response=sql.strip('\n'))
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
@@ -896,5 +939,56 @@ class ForeignDataWrapperView(PGChildNodeView):
|
|||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@check_precondition
|
||||||
|
def fetch_objects_to_compare(self, sid, did):
|
||||||
|
"""
|
||||||
|
This function will fetch the list of all the FDWs for
|
||||||
|
specified database id.
|
||||||
|
|
||||||
|
:param sid: Server Id
|
||||||
|
:param did: Database Id
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
res = dict()
|
||||||
|
|
||||||
|
sql = render_template("/".join([self.template_path,
|
||||||
|
'properties.sql']))
|
||||||
|
status, rset = self.conn.execute_2darray(sql)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=rset)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
status, data = self._fetch_properties(row['oid'])
|
||||||
|
if status:
|
||||||
|
res[row['name']] = data
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_sql_from_diff(self, **kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to get the DDL/DML statements.
|
||||||
|
:param kwargs
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
gid = kwargs.get('gid')
|
||||||
|
sid = kwargs.get('sid')
|
||||||
|
did = kwargs.get('did')
|
||||||
|
oid = kwargs.get('oid')
|
||||||
|
data = kwargs.get('data', None)
|
||||||
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
sql, name = self.get_sql(gid=gid, sid=sid, did=did, data=data,
|
||||||
|
fid=oid)
|
||||||
|
else:
|
||||||
|
if drop_sql:
|
||||||
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
|
fid=oid, only_sql=True)
|
||||||
|
else:
|
||||||
|
sql = self.sql(gid=gid, sid=sid, did=did, fid=oid,
|
||||||
|
json_resp=False)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
SchemaDiffRegistry(blueprint.node_type, ForeignDataWrapperView, 'Database')
|
||||||
ForeignDataWrapperView.register_node_view(blueprint)
|
ForeignDataWrapperView.register_node_view(blueprint)
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
|||||||
make_response as ajax_response, gone
|
make_response as ajax_response, gone
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||||
|
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||||
|
|
||||||
|
|
||||||
class ForeignServerModule(CollectionNodeModule):
|
class ForeignServerModule(CollectionNodeModule):
|
||||||
@@ -98,7 +100,7 @@ class ForeignServerModule(CollectionNodeModule):
|
|||||||
blueprint = ForeignServerModule(__name__)
|
blueprint = ForeignServerModule(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ForeignServerView(PGChildNodeView):
|
class ForeignServerView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||||
"""
|
"""
|
||||||
class ForeignServerView(PGChildNodeView)
|
class ForeignServerView(PGChildNodeView)
|
||||||
|
|
||||||
@@ -187,6 +189,8 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
'dependent': [{'get': 'dependents'}]
|
'dependent': [{'get': 'dependents'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
keys_to_ignore = ['oid', 'oid-2', 'fdwid']
|
||||||
|
|
||||||
def check_precondition(f):
|
def check_precondition(f):
|
||||||
"""
|
"""
|
||||||
This function will behave as a decorator which will checks
|
This function will behave as a decorator which will checks
|
||||||
@@ -269,7 +273,7 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
for row in r_set['rows']:
|
for row in r_set['rows']:
|
||||||
res.append(
|
res.append(
|
||||||
self.blueprint.generate_browser_node(
|
self.blueprint.generate_browser_node(
|
||||||
row['fsrvid'],
|
row['oid'],
|
||||||
fid,
|
fid,
|
||||||
row['name'],
|
row['name'],
|
||||||
icon="icon-foreign_server"
|
icon="icon-foreign_server"
|
||||||
@@ -305,7 +309,7 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
|
|
||||||
return make_json_response(
|
return make_json_response(
|
||||||
data=self.blueprint.generate_browser_node(
|
data=self.blueprint.generate_browser_node(
|
||||||
row['fsrvid'],
|
row['oid'],
|
||||||
fid,
|
fid,
|
||||||
row['name'],
|
row['name'],
|
||||||
icon="icon-foreign_server"
|
icon="icon-foreign_server"
|
||||||
@@ -328,22 +332,36 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
fid: foreign data wrapper ID
|
fid: foreign data wrapper ID
|
||||||
fsid: foreign server ID
|
fsid: foreign server ID
|
||||||
"""
|
"""
|
||||||
|
status, res = self._fetch_properties(fsid)
|
||||||
|
if not status:
|
||||||
|
return res
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def _fetch_properties(self, fsid):
|
||||||
|
"""
|
||||||
|
This function fetch the properties of the Foreign server.
|
||||||
|
:param fsid:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
sql = render_template("/".join([self.template_path,
|
sql = render_template("/".join([self.template_path,
|
||||||
self._PROPERTIES_SQL]),
|
self._PROPERTIES_SQL]),
|
||||||
fsid=fsid, conn=self.conn)
|
fsid=fsid, conn=self.conn)
|
||||||
status, res = self.conn.execute_dict(sql)
|
|
||||||
|
|
||||||
|
status, res = self.conn.execute_dict(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return False, internal_server_error(errormsg=res)
|
||||||
|
|
||||||
if len(res['rows']) == 0:
|
if len(res['rows']) == 0:
|
||||||
return gone(
|
return False, gone(
|
||||||
gettext("Could not find the foreign server information.")
|
gettext("Could not find the foreign server information.")
|
||||||
)
|
)
|
||||||
|
|
||||||
res['rows'][0]['is_sys_obj'] = (
|
res['rows'][0]['is_sys_obj'] = (
|
||||||
res['rows'][0]['fsrvid'] <= self.datlastsysoid)
|
res['rows'][0]['oid'] <= self.datlastsysoid)
|
||||||
|
|
||||||
if res['rows'][0]['fsrvoptions'] is not None:
|
if res['rows'][0]['fsrvoptions'] is not None:
|
||||||
res['rows'][0]['fsrvoptions'] = tokenize_options(
|
res['rows'][0]['fsrvoptions'] = tokenize_options(
|
||||||
@@ -354,9 +372,8 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
fsid=fsid
|
fsid=fsid
|
||||||
)
|
)
|
||||||
status, fs_rv_acl_res = self.conn.execute_dict(sql)
|
status, fs_rv_acl_res = self.conn.execute_dict(sql)
|
||||||
|
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=fs_rv_acl_res)
|
return False, internal_server_error(errormsg=fs_rv_acl_res)
|
||||||
|
|
||||||
for row in fs_rv_acl_res['rows']:
|
for row in fs_rv_acl_res['rows']:
|
||||||
privilege = parse_priv_from_db(row)
|
privilege = parse_priv_from_db(row)
|
||||||
@@ -365,10 +382,7 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
else:
|
else:
|
||||||
res['rows'][0][row['deftype']] = [privilege]
|
res['rows'][0][row['deftype']] = [privilege]
|
||||||
|
|
||||||
return ajax_response(
|
return True, res['rows'][0]
|
||||||
response=res['rows'][0],
|
|
||||||
status=200
|
|
||||||
)
|
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def create(self, gid, sid, did, fid):
|
def create(self, gid, sid, did, fid):
|
||||||
@@ -439,7 +453,7 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
node=self.blueprint.generate_browser_node(
|
node=self.blueprint.generate_browser_node(
|
||||||
r_set['rows'][0]['fsrvid'],
|
r_set['rows'][0]['oid'],
|
||||||
fid,
|
fid,
|
||||||
r_set['rows'][0]['name'],
|
r_set['rows'][0]['name'],
|
||||||
icon="icon-foreign_server"
|
icon="icon-foreign_server"
|
||||||
@@ -488,8 +502,31 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return internal_server_error(errormsg=str(e))
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_delete_data(cmd, fsid, request_object):
|
||||||
|
"""
|
||||||
|
This function is used to get the data and cascade information.
|
||||||
|
:param cmd: Command
|
||||||
|
:param fsid: Object ID
|
||||||
|
:param request_object: request object
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
cascade = False
|
||||||
|
# Below will decide if it's simple drop or drop with cascade call
|
||||||
|
if cmd == 'delete':
|
||||||
|
# This is a cascade operation
|
||||||
|
cascade = True
|
||||||
|
|
||||||
|
if fsid is None:
|
||||||
|
data = request_object.form if request_object.form else \
|
||||||
|
json.loads(request_object.data, encoding='utf-8')
|
||||||
|
else:
|
||||||
|
data = {'ids': [fsid]}
|
||||||
|
|
||||||
|
return cascade, data
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def delete(self, gid, sid, did, fid, fsid=None):
|
def delete(self, gid, sid, did, fid, fsid=None, only_sql=False):
|
||||||
"""
|
"""
|
||||||
This function will delete the selected foreign server node.
|
This function will delete the selected foreign server node.
|
||||||
|
|
||||||
@@ -499,20 +536,10 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
fid: foreign data wrapper ID
|
fid: foreign data wrapper ID
|
||||||
fsid: foreign server ID
|
fsid: foreign server ID
|
||||||
|
only_sql:
|
||||||
"""
|
"""
|
||||||
|
# get the value of cascade and data
|
||||||
if fsid is None:
|
cascade, data = self.get_delete_data(self.cmd, fsid, request)
|
||||||
data = request.form if request.form else json.loads(
|
|
||||||
request.data, encoding='utf-8'
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
data = {'ids': [fsid]}
|
|
||||||
|
|
||||||
if self.cmd == 'delete':
|
|
||||||
# This is a cascade operation
|
|
||||||
cascade = True
|
|
||||||
else:
|
|
||||||
cascade = False
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for fsid in data['ids']:
|
for fsid in data['ids']:
|
||||||
@@ -542,6 +569,11 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
self._DELETE_SQL]),
|
self._DELETE_SQL]),
|
||||||
name=name, cascade=cascade,
|
name=name, cascade=cascade,
|
||||||
conn=self.conn)
|
conn=self.conn)
|
||||||
|
|
||||||
|
# Used for schema diff tool
|
||||||
|
if only_sql:
|
||||||
|
return sql.strip('\n')
|
||||||
|
|
||||||
status, res = self.conn.execute_scalar(sql)
|
status, res = self.conn.execute_scalar(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
@@ -674,7 +706,8 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
is_valid_changed_options=is_valid_changed_options,
|
is_valid_changed_options=is_valid_changed_options,
|
||||||
conn=self.conn
|
conn=self.conn
|
||||||
)
|
)
|
||||||
return sql, data['name'] if 'name' in data else old_data['name']
|
return sql.strip('\n'), \
|
||||||
|
data['name'] if 'name' in data else old_data['name']
|
||||||
else:
|
else:
|
||||||
sql = render_template("/".join([self.template_path,
|
sql = render_template("/".join([self.template_path,
|
||||||
self._PROPERTIES_SQL]),
|
self._PROPERTIES_SQL]),
|
||||||
@@ -704,7 +737,7 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
return sql, data['name']
|
return sql, data['name']
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def sql(self, gid, sid, did, fid, fsid):
|
def sql(self, gid, sid, did, fid, fsid, json_resp=True):
|
||||||
"""
|
"""
|
||||||
This function will generate sql to show it in sql pane for the
|
This function will generate sql to show it in sql pane for the
|
||||||
selected foreign server node.
|
selected foreign server node.
|
||||||
@@ -715,6 +748,7 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
fid: Foreign data wrapper ID
|
fid: Foreign data wrapper ID
|
||||||
fsid: Foreign server ID
|
fsid: Foreign server ID
|
||||||
|
json_resp:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
sql = render_template("/".join([self.template_path,
|
sql = render_template("/".join([self.template_path,
|
||||||
@@ -728,6 +762,9 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
gettext("Could not find the foreign server information.")
|
gettext("Could not find the foreign server information.")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if fid is None and 'fdwid' in res['rows'][0]:
|
||||||
|
fid = res['rows'][0]['fdwid']
|
||||||
|
|
||||||
is_valid_options = False
|
is_valid_options = False
|
||||||
if res['rows'][0]['fsrvoptions'] is not None:
|
if res['rows'][0]['fsrvoptions'] is not None:
|
||||||
res['rows'][0]['fsrvoptions'] = tokenize_options(
|
res['rows'][0]['fsrvoptions'] = tokenize_options(
|
||||||
@@ -782,6 +819,9 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
|
|
||||||
sql = sql_header + sql
|
sql = sql_header + sql
|
||||||
|
|
||||||
|
if not json_resp:
|
||||||
|
return sql.strip('\n')
|
||||||
|
|
||||||
return ajax_response(response=sql.strip('\n'))
|
return ajax_response(response=sql.strip('\n'))
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
@@ -836,5 +876,57 @@ class ForeignServerView(PGChildNodeView):
|
|||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@check_precondition
|
||||||
|
def fetch_objects_to_compare(self, sid, did):
|
||||||
|
"""
|
||||||
|
This function will fetch the list of all the FDWs for
|
||||||
|
specified database id.
|
||||||
|
|
||||||
|
:param sid: Server Id
|
||||||
|
:param did: Database Id
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
res = dict()
|
||||||
|
|
||||||
|
sql = render_template("/".join([self.template_path,
|
||||||
|
'properties.sql']))
|
||||||
|
status, rset = self.conn.execute_2darray(sql)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=rset)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
status, data = self._fetch_properties(row['oid'])
|
||||||
|
if status:
|
||||||
|
res[row['name']] = data
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_sql_from_diff(self, **kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to get the DDL/DML statements.
|
||||||
|
:param kwargs
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
gid = kwargs.get('gid')
|
||||||
|
sid = kwargs.get('sid')
|
||||||
|
did = kwargs.get('did')
|
||||||
|
fdw_id = kwargs.get('fdwid')
|
||||||
|
oid = kwargs.get('oid')
|
||||||
|
data = kwargs.get('data', None)
|
||||||
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
sql, name = self.get_sql(gid=gid, sid=sid, did=did, data=data,
|
||||||
|
fid=fdw_id, fsid=oid)
|
||||||
|
else:
|
||||||
|
if drop_sql:
|
||||||
|
sql = self.delete(gid=gid, sid=sid, did=did, fid=fdw_id,
|
||||||
|
fsid=oid, only_sql=True)
|
||||||
|
else:
|
||||||
|
sql = self.sql(gid=gid, sid=sid, did=did, fid=fdw_id,
|
||||||
|
fsid=oid, json_resp=False)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
SchemaDiffRegistry(blueprint.node_type, ForeignServerView, 'Database')
|
||||||
ForeignServerView.register_node_view(blueprint)
|
ForeignServerView.register_node_view(blueprint)
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ define('pgadmin.node.foreign_server', [
|
|||||||
|
|
||||||
// Defining model for foreign server node
|
// Defining model for foreign server node
|
||||||
model: pgAdmin.Browser.Node.Model.extend({
|
model: pgAdmin.Browser.Node.Model.extend({
|
||||||
idAttribute: 'fsrvid',
|
idAttribute: 'oid',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: undefined,
|
name: undefined,
|
||||||
fsrvtype: undefined,
|
fsrvtype: undefined,
|
||||||
@@ -135,7 +135,7 @@ define('pgadmin.node.foreign_server', [
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},{
|
},{
|
||||||
id: 'fsrvid', label: gettext('OID'), cell: 'string',
|
id: 'oid', label: gettext('OID'), cell: 'string',
|
||||||
type: 'text', mode: ['properties'],
|
type: 'text', mode: ['properties'],
|
||||||
},{
|
},{
|
||||||
id: 'fsrvowner', label: gettext('Owner'), type: 'text',
|
id: 'fsrvowner', label: gettext('Owner'), type: 'text',
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ FROM pg_foreign_data_wrapper fdw
|
|||||||
LEFT OUTER JOIN pg_description des ON (des.objoid=fdw.oid AND des.objsubid=0 AND des.classoid='pg_foreign_data_wrapper'::regclass)
|
LEFT OUTER JOIN pg_description des ON (des.objoid=fdw.oid AND des.objsubid=0 AND des.classoid='pg_foreign_data_wrapper'::regclass)
|
||||||
WHERE fdw.oid={{fdwid}}::oid
|
WHERE fdw.oid={{fdwid}}::oid
|
||||||
{% else %}
|
{% else %}
|
||||||
SELECT srv.oid as fsrvid, srvname as name, srvtype as fsrvtype, srvversion as fsrvversion, fdw.fdwname as fdwname, description,
|
SELECT srv.oid, srvname as name, srvfdw as fdwid, srvtype as fsrvtype, srvversion as fsrvversion,
|
||||||
array_to_string(srvoptions, ',') AS fsrvoptions,
|
fdw.fdwname as fdwname, description, array_to_string(srvoptions, ',') AS fsrvoptions,
|
||||||
pg_get_userbyid(srvowner) as fsrvowner, array_to_string(srvacl::text[], ', ') as acl
|
pg_get_userbyid(srvowner) as fsrvowner, array_to_string(srvacl::text[], ', ') as acl
|
||||||
FROM pg_foreign_server srv
|
FROM pg_foreign_server srv
|
||||||
LEFT OUTER JOIN pg_foreign_data_wrapper fdw on fdw.oid=srvfdw
|
LEFT OUTER JOIN pg_foreign_data_wrapper fdw on fdw.oid=srvfdw
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ FROM pg_foreign_data_wrapper fdw
|
|||||||
LEFT OUTER JOIN pg_description des ON (des.objoid=fdw.oid AND des.objsubid=0 AND des.classoid='pg_foreign_data_wrapper'::regclass)
|
LEFT OUTER JOIN pg_description des ON (des.objoid=fdw.oid AND des.objsubid=0 AND des.classoid='pg_foreign_data_wrapper'::regclass)
|
||||||
WHERE fdw.oid={{fdwid}}::oid
|
WHERE fdw.oid={{fdwid}}::oid
|
||||||
{% else %}
|
{% else %}
|
||||||
SELECT srv.oid as fsrvid, srvname as name, srvtype as fsrvtype, srvversion as fsrvversion, fdw.fdwname as fdwname, description,
|
SELECT srv.oid, srvname as name, srvtype as fsrvtype, srvversion as fsrvversion, fdw.fdwname as fdwname, description,
|
||||||
array_to_string(srvoptions, ',') AS fsrvoptions,
|
array_to_string(srvoptions, ',') AS fsrvoptions,
|
||||||
pg_get_userbyid(srvowner) as fsrvowner, array_to_string(srvacl::text[], ', ') as acl
|
pg_get_userbyid(srvowner) as fsrvowner, array_to_string(srvacl::text[], ', ') as acl
|
||||||
FROM pg_foreign_server srv
|
FROM pg_foreign_server srv
|
||||||
|
|||||||
@@ -1,10 +1,37 @@
|
|||||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||||
{% if data %}
|
{% if data %}
|
||||||
|
{% if (data.fsrvtype is defined and data.fsrvtype != o_data.fsrvtype) or (data.fdwname is defined and data.fdwname != o_data.fdwname) %}
|
||||||
|
{% set fsrvtype = o_data.fsrvtype %}
|
||||||
|
{% set fdwname = o_data.fdwname %}
|
||||||
|
{% if data.fsrvtype is defined %}
|
||||||
|
{% set fsrvtype = data.fsrvtype %}
|
||||||
|
{% endif %}
|
||||||
|
{% if data.fdwname is defined %}
|
||||||
|
{% set fdwname = data.fdwname %}
|
||||||
|
{% endif %}
|
||||||
|
-- WARNING:
|
||||||
|
-- We have found the difference in SERVER TYPE OR FOREIGN DATA WRAPPER
|
||||||
|
-- so we need to drop the existing foreign server first and re-create it.
|
||||||
|
DROP SERVER {{ conn|qtIdent(o_data.name) }};
|
||||||
|
|
||||||
|
CREATE SERVER {{ conn|qtIdent(o_data.name) }}{% if data.fsrvtype or o_data.fsrvtype %}
|
||||||
|
|
||||||
|
TYPE {{ fsrvtype|qtLiteral }}{% endif %}{% if o_data.fsrvversion %}
|
||||||
|
|
||||||
|
VERSION {{ o_data.fsrvversion|qtLiteral }}{%-endif %}{% if o_data.fdwname %}
|
||||||
|
|
||||||
|
FOREIGN DATA WRAPPER {{ conn|qtIdent(fdwname) }}{% endif %}{% if o_data.fsrvoptions %}
|
||||||
|
|
||||||
|
OPTIONS ({% for variable in o_data.fsrvoptions %}{% if loop.index != 1 %}, {% endif %}
|
||||||
|
{{ conn|qtIdent(variable.fsrvoption) }} {{ variable.fsrvvalue|qtLiteral }}{% endfor %}){% endif %};
|
||||||
|
|
||||||
|
{% else %}
|
||||||
{# ============= Update foreign server name ============= #}
|
{# ============= Update foreign server name ============= #}
|
||||||
{% if data.name != o_data.name %}
|
{% if data.name != o_data.name %}
|
||||||
ALTER SERVER {{ conn|qtIdent(o_data.name) }}
|
ALTER SERVER {{ conn|qtIdent(o_data.name) }}
|
||||||
RENAME TO {{ conn|qtIdent(data.name) }};
|
RENAME TO {{ conn|qtIdent(data.name) }};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# ============= Update foreign server owner ============= #}
|
{# ============= Update foreign server owner ============= #}
|
||||||
{% if data.fsrvowner and data.fsrvowner != o_data.fsrvowner %}
|
{% if data.fsrvowner and data.fsrvowner != o_data.fsrvowner %}
|
||||||
@@ -13,7 +40,7 @@ ALTER SERVER {{ conn|qtIdent(data.name) }}
|
|||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# ============= Update foreign server version ============= #}
|
{# ============= Update foreign server version ============= #}
|
||||||
{% if data.fsrvversion and data.fsrvversion != o_data.fsrvversion %}
|
{% if data.fsrvversion is defined and data.fsrvversion != o_data.fsrvversion %}
|
||||||
ALTER SERVER {{ conn|qtIdent(data.name) }}
|
ALTER SERVER {{ conn|qtIdent(data.name) }}
|
||||||
VERSION {{ data.fsrvversion|qtLiteral }};
|
VERSION {{ data.fsrvversion|qtLiteral }};
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
|||||||
make_response as ajax_response, gone
|
make_response as ajax_response, gone
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||||
|
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||||
|
|
||||||
|
|
||||||
class UserMappingModule(CollectionNodeModule):
|
class UserMappingModule(CollectionNodeModule):
|
||||||
@@ -114,7 +116,7 @@ class UserMappingModule(CollectionNodeModule):
|
|||||||
blueprint = UserMappingModule(__name__)
|
blueprint = UserMappingModule(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UserMappingView(PGChildNodeView):
|
class UserMappingView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||||
"""
|
"""
|
||||||
class UserMappingView(PGChildNodeView)
|
class UserMappingView(PGChildNodeView)
|
||||||
|
|
||||||
@@ -204,6 +206,8 @@ class UserMappingView(PGChildNodeView):
|
|||||||
'dependent': [{'get': 'dependents'}]
|
'dependent': [{'get': 'dependents'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
keys_to_ignore = ['oid', 'oid-2', 'fdwid', 'fsid']
|
||||||
|
|
||||||
def check_precondition(f):
|
def check_precondition(f):
|
||||||
"""
|
"""
|
||||||
This function will behave as a decorator which will checks
|
This function will behave as a decorator which will checks
|
||||||
@@ -287,7 +291,7 @@ class UserMappingView(PGChildNodeView):
|
|||||||
for row in r_set['rows']:
|
for row in r_set['rows']:
|
||||||
res.append(
|
res.append(
|
||||||
self.blueprint.generate_browser_node(
|
self.blueprint.generate_browser_node(
|
||||||
row['um_oid'],
|
row['oid'],
|
||||||
fsid,
|
fsid,
|
||||||
row['name'],
|
row['name'],
|
||||||
icon="icon-user_mapping"
|
icon="icon-user_mapping"
|
||||||
@@ -322,7 +326,7 @@ class UserMappingView(PGChildNodeView):
|
|||||||
for row in r_set['rows']:
|
for row in r_set['rows']:
|
||||||
return make_json_response(
|
return make_json_response(
|
||||||
data=self.blueprint.generate_browser_node(
|
data=self.blueprint.generate_browser_node(
|
||||||
row['um_oid'],
|
row['oid'],
|
||||||
fsid,
|
fsid,
|
||||||
row['name'],
|
row['name'],
|
||||||
icon="icon-user_mapping"
|
icon="icon-user_mapping"
|
||||||
@@ -346,32 +350,44 @@ class UserMappingView(PGChildNodeView):
|
|||||||
fsid: Foreign server ID
|
fsid: Foreign server ID
|
||||||
umid: User mapping ID
|
umid: User mapping ID
|
||||||
"""
|
"""
|
||||||
|
status, res = self._fetch_properties(umid)
|
||||||
|
if not status:
|
||||||
|
return res
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def _fetch_properties(self, umid):
|
||||||
|
"""
|
||||||
|
This function fetch the properties of the User Mapping.
|
||||||
|
:param umid:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
sql = render_template("/".join([self.template_path,
|
sql = render_template("/".join([self.template_path,
|
||||||
self._PROPERTIES_SQL]),
|
self._PROPERTIES_SQL]),
|
||||||
umid=umid, conn=self.conn)
|
umid=umid, conn=self.conn)
|
||||||
status, res = self.conn.execute_dict(sql)
|
|
||||||
|
|
||||||
|
status, res = self.conn.execute_dict(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return False, internal_server_error(errormsg=res)
|
||||||
|
|
||||||
if len(res['rows']) == 0:
|
if len(res['rows']) == 0:
|
||||||
return gone(
|
return False, gone(
|
||||||
gettext("Could not find the user mapping information.")
|
gettext("Could not find the user mapping information.")
|
||||||
)
|
)
|
||||||
|
|
||||||
res['rows'][0]['is_sys_obj'] = (
|
res['rows'][0]['is_sys_obj'] = (
|
||||||
res['rows'][0]['um_oid'] <= self.datlastsysoid)
|
res['rows'][0]['oid'] <= self.datlastsysoid)
|
||||||
|
|
||||||
if res['rows'][0]['umoptions'] is not None:
|
if res['rows'][0]['umoptions'] is not None:
|
||||||
res['rows'][0]['umoptions'] = tokenize_options(
|
res['rows'][0]['umoptions'] = tokenize_options(
|
||||||
res['rows'][0]['umoptions'],
|
res['rows'][0]['umoptions'],
|
||||||
'umoption', 'umvalue'
|
'umoption', 'umvalue'
|
||||||
)
|
)
|
||||||
return ajax_response(
|
|
||||||
response=res['rows'][0],
|
return True, res['rows'][0]
|
||||||
status=200
|
|
||||||
)
|
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def create(self, gid, sid, did, fid, fsid):
|
def create(self, gid, sid, did, fid, fsid):
|
||||||
@@ -443,7 +459,7 @@ class UserMappingView(PGChildNodeView):
|
|||||||
for row in r_set['rows']:
|
for row in r_set['rows']:
|
||||||
return jsonify(
|
return jsonify(
|
||||||
node=self.blueprint.generate_browser_node(
|
node=self.blueprint.generate_browser_node(
|
||||||
row['um_oid'],
|
row['oid'],
|
||||||
fsid,
|
fsid,
|
||||||
row['name'],
|
row['name'],
|
||||||
icon='icon-user_mapping'
|
icon='icon-user_mapping'
|
||||||
@@ -492,8 +508,31 @@ class UserMappingView(PGChildNodeView):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return internal_server_error(errormsg=str(e))
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_delete_data(cmd, umid, request_object):
|
||||||
|
"""
|
||||||
|
This function is used to get the data and cascade information.
|
||||||
|
:param cmd: Command
|
||||||
|
:param umid: Object ID
|
||||||
|
:param request_object: request object
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
cascade = False
|
||||||
|
# Below will decide if it's simple drop or drop with cascade call
|
||||||
|
if cmd == 'delete':
|
||||||
|
# This is a cascade operation
|
||||||
|
cascade = True
|
||||||
|
|
||||||
|
if umid is None:
|
||||||
|
data = request_object.form if request_object.form else \
|
||||||
|
json.loads(request_object.data, encoding='utf-8')
|
||||||
|
else:
|
||||||
|
data = {'ids': [umid]}
|
||||||
|
|
||||||
|
return cascade, data
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def delete(self, gid, sid, did, fid, fsid, umid=None):
|
def delete(self, gid, sid, did, fid, fsid, **kwargs):
|
||||||
"""
|
"""
|
||||||
This function will delete the selected user mapping node.
|
This function will delete the selected user mapping node.
|
||||||
|
|
||||||
@@ -503,20 +542,15 @@ class UserMappingView(PGChildNodeView):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
fid: foreign data wrapper ID
|
fid: foreign data wrapper ID
|
||||||
fsid: foreign server ID
|
fsid: foreign server ID
|
||||||
umid: User mapping ID
|
**kwargs:
|
||||||
"""
|
|
||||||
if umid is None:
|
|
||||||
data = request.form if request.form else json.loads(
|
|
||||||
request.data, encoding='utf-8'
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
data = {'ids': [umid]}
|
|
||||||
|
|
||||||
if self.cmd == 'delete':
|
"""
|
||||||
# This is a cascade operation
|
|
||||||
cascade = True
|
umid = kwargs.get('umid', None)
|
||||||
else:
|
only_sql = kwargs.get('only_sql', False)
|
||||||
cascade = False
|
|
||||||
|
# get the value of cascade and data
|
||||||
|
cascade, data = self.get_delete_data(self.cmd, umid, request)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for umid in data['ids']:
|
for umid in data['ids']:
|
||||||
@@ -564,6 +598,11 @@ class UserMappingView(PGChildNodeView):
|
|||||||
self._DELETE_SQL]),
|
self._DELETE_SQL]),
|
||||||
data=data, name=name, cascade=cascade,
|
data=data, name=name, cascade=cascade,
|
||||||
conn=self.conn)
|
conn=self.conn)
|
||||||
|
|
||||||
|
# Used for schema diff tool
|
||||||
|
if only_sql:
|
||||||
|
return sql
|
||||||
|
|
||||||
status, res = self.conn.execute_scalar(sql)
|
status, res = self.conn.execute_scalar(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
@@ -707,7 +746,7 @@ class UserMappingView(PGChildNodeView):
|
|||||||
return sql, data['name']
|
return sql, data['name']
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def sql(self, gid, sid, did, fid, fsid, umid):
|
def sql(self, gid, sid, did, fid, fsid, **kwargs):
|
||||||
"""
|
"""
|
||||||
This function will generate sql to show it in sql pane for
|
This function will generate sql to show it in sql pane for
|
||||||
the selected user mapping node.
|
the selected user mapping node.
|
||||||
@@ -718,8 +757,10 @@ class UserMappingView(PGChildNodeView):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
fid: Foreign data wrapper ID
|
fid: Foreign data wrapper ID
|
||||||
fsid: Foreign server ID
|
fsid: Foreign server ID
|
||||||
umid: User mapping ID
|
kwargs:
|
||||||
"""
|
"""
|
||||||
|
umid = kwargs.get('umid')
|
||||||
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
sql = render_template("/".join([self.template_path,
|
sql = render_template("/".join([self.template_path,
|
||||||
self._PROPERTIES_SQL]),
|
self._PROPERTIES_SQL]),
|
||||||
@@ -732,6 +773,9 @@ class UserMappingView(PGChildNodeView):
|
|||||||
gettext("Could not find the user mapping information.")
|
gettext("Could not find the user mapping information.")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if fsid is None and 'fsid' in res['rows'][0]:
|
||||||
|
fsid = res['rows'][0]['fsid']
|
||||||
|
|
||||||
is_valid_options = False
|
is_valid_options = False
|
||||||
if res['rows'][0]['umoptions'] is not None:
|
if res['rows'][0]['umoptions'] is not None:
|
||||||
res['rows'][0]['umoptions'] = tokenize_options(
|
res['rows'][0]['umoptions'] = tokenize_options(
|
||||||
@@ -767,6 +811,9 @@ class UserMappingView(PGChildNodeView):
|
|||||||
|
|
||||||
sql = sql_header + sql
|
sql = sql_header + sql
|
||||||
|
|
||||||
|
if not json_resp:
|
||||||
|
return sql.strip('\n')
|
||||||
|
|
||||||
return ajax_response(response=sql.strip('\n'))
|
return ajax_response(response=sql.strip('\n'))
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
@@ -810,5 +857,57 @@ class UserMappingView(PGChildNodeView):
|
|||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@check_precondition
|
||||||
|
def fetch_objects_to_compare(self, sid, did):
|
||||||
|
"""
|
||||||
|
This function will fetch the list of all the FDWs for
|
||||||
|
specified database id.
|
||||||
|
|
||||||
|
:param sid: Server Id
|
||||||
|
:param did: Database Id
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
res = dict()
|
||||||
|
|
||||||
|
sql = render_template("/".join([self.template_path,
|
||||||
|
'properties.sql']))
|
||||||
|
status, rset = self.conn.execute_2darray(sql)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=rset)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
status, data = self._fetch_properties(row['oid'])
|
||||||
|
if status:
|
||||||
|
res[row['name']] = data
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_sql_from_diff(self, **kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to get the DDL/DML statements.
|
||||||
|
:param kwargs:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
gid = kwargs.get('gid')
|
||||||
|
sid = kwargs.get('sid')
|
||||||
|
did = kwargs.get('did')
|
||||||
|
fid = kwargs.get('fdwid')
|
||||||
|
fsid = kwargs.get('fsid')
|
||||||
|
oid = kwargs.get('oid')
|
||||||
|
data = kwargs.get('data', None)
|
||||||
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
sql, name = self.get_sql(data=data, fsid=fsid, umid=oid)
|
||||||
|
else:
|
||||||
|
if drop_sql:
|
||||||
|
sql = self.delete(gid=gid, sid=sid, did=did, fid=fid,
|
||||||
|
fsid=fsid, umid=oid, only_sql=True)
|
||||||
|
else:
|
||||||
|
sql = self.sql(gid=gid, sid=sid, did=did, fid=fid, fsid=fsid,
|
||||||
|
umid=oid, json_resp=False)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
SchemaDiffRegistry(blueprint.node_type, UserMappingView, 'Database')
|
||||||
UserMappingView.register_node_view(blueprint)
|
UserMappingView.register_node_view(blueprint)
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ SELECT srvname as name FROM pg_foreign_server srv LEFT OUTER JOIN pg_foreign_dat
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{# ============= Drop/Delete cascade user mapping ============= #}
|
{# ============= Drop/Delete cascade user mapping ============= #}
|
||||||
{% if name and data %}
|
{% if name and data %}
|
||||||
DROP USER MAPPING FOR {% if data.name == "CURRENT_USER" or data.name == "PUBLIC" %}{{ data.name }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} SERVER {{ conn|qtIdent(name) }}
|
DROP USER MAPPING FOR {% if data.name == "CURRENT_USER" or data.name == "PUBLIC" %}{{ data.name }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} SERVER {{ conn|qtIdent(name) }};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -4,10 +4,15 @@ SELECT srv.oid as fsrvid, srvname as name
|
|||||||
FROM pg_foreign_server srv
|
FROM pg_foreign_server srv
|
||||||
LEFT OUTER JOIN pg_description des ON (des.objoid=srv.oid AND des.objsubid=0 AND des.classoid='pg_foreign_server'::regclass)
|
LEFT OUTER JOIN pg_description des ON (des.objoid=srv.oid AND des.objsubid=0 AND des.classoid='pg_foreign_server'::regclass)
|
||||||
WHERE srv.oid = {{fserid}}::oid
|
WHERE srv.oid = {{fserid}}::oid
|
||||||
{% endif %}
|
{% elif fsid or umid %}
|
||||||
{% if fsid or umid %}
|
SELECT u.umid AS oid, u.usename AS name, u.srvid AS fsid, array_to_string(u.umoptions, ',') AS umoptions, fs.srvfdw AS fdwid
|
||||||
SELECT u.umid AS um_oid, u.usename as name, array_to_string(u.umoptions, ',') AS umoptions
|
|
||||||
FROM pg_user_mappings u
|
FROM pg_user_mappings u
|
||||||
|
LEFT JOIN pg_foreign_server fs ON fs.oid = u.srvid
|
||||||
{% if fsid %} WHERE u.srvid = {{fsid}}::oid {% endif %} {% if umid %} WHERE u.umid= {{umid}}::oid {% endif %}
|
{% if fsid %} WHERE u.srvid = {{fsid}}::oid {% endif %} {% if umid %} WHERE u.umid= {{umid}}::oid {% endif %}
|
||||||
ORDER BY 2;
|
ORDER BY 2;
|
||||||
|
{% else %}
|
||||||
|
SELECT u.umid AS oid, u.usename AS name, u.srvid AS fsid, array_to_string(u.umoptions, ',') AS umoptions, fs.srvfdw AS fdwid
|
||||||
|
FROM pg_user_mappings u
|
||||||
|
LEFT JOIN pg_foreign_server fs ON fs.oid = u.srvid
|
||||||
|
ORDER BY 2;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ define('pgadmin.node.foreign_data_wrapper', [
|
|||||||
|
|
||||||
// Defining model for foreign data wrapper node
|
// Defining model for foreign data wrapper node
|
||||||
model: pgBrowser.Node.Model.extend({
|
model: pgBrowser.Node.Model.extend({
|
||||||
idAttribute: 'fdwoid',
|
idAttribute: 'oid',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: undefined,
|
name: undefined,
|
||||||
fdwowner: undefined,
|
fdwowner: undefined,
|
||||||
@@ -138,7 +138,7 @@ define('pgadmin.node.foreign_data_wrapper', [
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},{
|
},{
|
||||||
id: 'fdwoid', label: gettext('OID'), cell: 'string',
|
id: 'oid', label: gettext('OID'), cell: 'string',
|
||||||
type: 'text', mode: ['properties'],
|
type: 'text', mode: ['properties'],
|
||||||
},{
|
},{
|
||||||
id: 'fdwowner', label: gettext('Owner'), type: 'text',
|
id: 'fdwowner', label: gettext('Owner'), type: 'text',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{# ============= Get all the properties of foreign data wrapper ============= #}
|
{# ============= Get all the properties of foreign data wrapper ============= #}
|
||||||
SELECT fdw.oid as fdwoid, fdwname as name, fdwhandler, fdwvalidator, description,
|
SELECT fdw.oid, fdwname as name, fdwhandler, fdwvalidator, description,
|
||||||
array_to_string(fdwoptions, ',') AS fdwoptions, pg_get_userbyid(fdwowner) as fdwowner, array_to_string(fdwacl::text[], ', ') as acl,
|
array_to_string(fdwoptions, ',') AS fdwoptions, pg_get_userbyid(fdwowner) as fdwowner, array_to_string(fdwacl::text[], ', ') as acl,
|
||||||
CASE
|
CASE
|
||||||
-- EPAS in redwood mode, concatenation of a string with NULL results as the original string
|
-- EPAS in redwood mode, concatenation of a string with NULL results as the original string
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
|||||||
VALIDATOR {{ data.fdwvalue }};
|
VALIDATOR {{ data.fdwvalue }};
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if data.fdwvalue == '' and data.fdwvalue != o_data.fdwvalue %}
|
{% if (data.fdwvalue == '' or data.fdwvalue == None) and data.fdwvalue != o_data.fdwvalue %}
|
||||||
ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
||||||
NO VALIDATOR;
|
NO VALIDATOR;
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
|||||||
HANDLER {{ data.fdwhan }};
|
HANDLER {{ data.fdwhan }};
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if data.fdwhan == '' and data.fdwhan != o_data.fdwhan %}
|
{% if (data.fdwhan == '' or data.fdwhan == None) and data.fdwhan != o_data.fdwhan %}
|
||||||
ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
||||||
NO HANDLER;
|
NO HANDLER;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{# ============= Get all the properties of foreign data wrapper ============= #}
|
{# ============= Get all the properties of foreign data wrapper ============= #}
|
||||||
SELECT fdw.oid as fdwoid, fdwname as name, fdwhandler, fdwvalidator, description,
|
SELECT fdw.oid, fdwname as name, fdwhandler, fdwvalidator, description,
|
||||||
array_to_string(fdwoptions, ',') AS fdwoptions, pg_get_userbyid(fdwowner) as fdwowner, array_to_string(fdwacl::text[], ', ') as acl,
|
array_to_string(fdwoptions, ',') AS fdwoptions, pg_get_userbyid(fdwowner) as fdwowner, array_to_string(fdwacl::text[], ', ') as acl,
|
||||||
CASE
|
CASE
|
||||||
-- EPAS in redwood mode, concatenation of a string with NULL results as the original string
|
-- EPAS in redwood mode, concatenation of a string with NULL results as the original string
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
|||||||
VALIDATOR {{ data.fdwvalue }};
|
VALIDATOR {{ data.fdwvalue }};
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if data.fdwvalue == '' and data.fdwvalue != o_data.fdwvalue %}
|
{% if (data.fdwvalue == '' or data.fdwvalue == None) and data.fdwvalue != o_data.fdwvalue %}
|
||||||
ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
||||||
NO VALIDATOR;
|
NO VALIDATOR;
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
|||||||
HANDLER {{ data.fdwhan }};
|
HANDLER {{ data.fdwhan }};
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if data.fdwhan == '' and data.fdwhan != o_data.fdwhan %}
|
{% if (data.fdwhan == '' or data.fdwhan == None) and data.fdwhan != o_data.fdwhan %}
|
||||||
ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}
|
||||||
NO HANDLER;
|
NO HANDLER;
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
|||||||
make_response as ajax_response, gone
|
make_response as ajax_response, gone
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry
|
||||||
|
from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare
|
||||||
|
|
||||||
|
|
||||||
class LanguageModule(CollectionNodeModule):
|
class LanguageModule(CollectionNodeModule):
|
||||||
@@ -105,7 +107,7 @@ class LanguageModule(CollectionNodeModule):
|
|||||||
blueprint = LanguageModule(__name__)
|
blueprint = LanguageModule(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LanguageView(PGChildNodeView):
|
class LanguageView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||||
"""
|
"""
|
||||||
class LanguageView(PGChildNodeView)
|
class LanguageView(PGChildNodeView)
|
||||||
|
|
||||||
@@ -338,6 +340,22 @@ class LanguageView(PGChildNodeView):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
lid: Language ID
|
lid: Language ID
|
||||||
"""
|
"""
|
||||||
|
status, res = self._fetch_properties(did, lid)
|
||||||
|
if not status:
|
||||||
|
return res
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def _fetch_properties(self, did, lid):
|
||||||
|
"""
|
||||||
|
This function fetch the properties of the extension.
|
||||||
|
:param did:
|
||||||
|
:param lid:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
||||||
lid=lid
|
lid=lid
|
||||||
@@ -345,10 +363,10 @@ class LanguageView(PGChildNodeView):
|
|||||||
status, res = self.conn.execute_dict(sql)
|
status, res = self.conn.execute_dict(sql)
|
||||||
|
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return False, internal_server_error(errormsg=res)
|
||||||
|
|
||||||
if len(res['rows']) == 0:
|
if len(res['rows']) == 0:
|
||||||
return gone(
|
return False, gone(
|
||||||
gettext("Could not find the language information.")
|
gettext("Could not find the language information.")
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -361,7 +379,7 @@ class LanguageView(PGChildNodeView):
|
|||||||
)
|
)
|
||||||
status, result = self.conn.execute_dict(sql)
|
status, result = self.conn.execute_dict(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=result)
|
return False, internal_server_error(errormsg=result)
|
||||||
|
|
||||||
# if no acl found then by default add public
|
# if no acl found then by default add public
|
||||||
if res['rows'][0]['acl'] is None:
|
if res['rows'][0]['acl'] is None:
|
||||||
@@ -396,10 +414,7 @@ class LanguageView(PGChildNodeView):
|
|||||||
|
|
||||||
res['rows'][0]['seclabels'] = seclabels
|
res['rows'][0]['seclabels'] = seclabels
|
||||||
|
|
||||||
return ajax_response(
|
return True, res['rows'][0]
|
||||||
response=res['rows'][0],
|
|
||||||
status=200
|
|
||||||
)
|
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def update(self, gid, sid, did, lid):
|
def update(self, gid, sid, did, lid):
|
||||||
@@ -498,7 +513,7 @@ class LanguageView(PGChildNodeView):
|
|||||||
return internal_server_error(errormsg=str(e))
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def delete(self, gid, sid, did, lid=None):
|
def delete(self, gid, sid, did, lid=None, only_sql=False):
|
||||||
"""
|
"""
|
||||||
This function will drop the language object
|
This function will drop the language object
|
||||||
|
|
||||||
@@ -507,6 +522,7 @@ class LanguageView(PGChildNodeView):
|
|||||||
sid: Server ID
|
sid: Server ID
|
||||||
did: Database ID
|
did: Database ID
|
||||||
lid: Language ID
|
lid: Language ID
|
||||||
|
only_sql:
|
||||||
"""
|
"""
|
||||||
if lid is None:
|
if lid is None:
|
||||||
data = request.form if request.form else json.loads(
|
data = request.form if request.form else json.loads(
|
||||||
@@ -538,8 +554,12 @@ class LanguageView(PGChildNodeView):
|
|||||||
"/".join([self.template_path, self._DELETE_SQL]),
|
"/".join([self.template_path, self._DELETE_SQL]),
|
||||||
lname=lname, cascade=cascade, conn=self.conn
|
lname=lname, cascade=cascade, conn=self.conn
|
||||||
)
|
)
|
||||||
status, res = self.conn.execute_scalar(sql)
|
|
||||||
|
|
||||||
|
# Used for schema diff tool
|
||||||
|
if only_sql:
|
||||||
|
return sql
|
||||||
|
|
||||||
|
status, res = self.conn.execute_scalar(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
|
|
||||||
@@ -690,7 +710,7 @@ class LanguageView(PGChildNodeView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def sql(self, gid, sid, did, lid):
|
def sql(self, gid, sid, did, lid, json_resp=True):
|
||||||
"""
|
"""
|
||||||
This function will generate sql to show in the sql pane for the
|
This function will generate sql to show in the sql pane for the
|
||||||
selected language node.
|
selected language node.
|
||||||
@@ -700,6 +720,7 @@ class LanguageView(PGChildNodeView):
|
|||||||
sid: Server ID
|
sid: Server ID
|
||||||
did: Database ID
|
did: Database ID
|
||||||
lid: Language ID
|
lid: Language ID
|
||||||
|
json_resp:
|
||||||
"""
|
"""
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
||||||
@@ -755,6 +776,9 @@ class LanguageView(PGChildNodeView):
|
|||||||
data=old_data, conn=self.conn
|
data=old_data, conn=self.conn
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not json_resp:
|
||||||
|
return sql.strip('\n')
|
||||||
|
|
||||||
return ajax_response(response=sql.strip('\n'))
|
return ajax_response(response=sql.strip('\n'))
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
@@ -793,5 +817,54 @@ class LanguageView(PGChildNodeView):
|
|||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@check_precondition
|
||||||
|
def fetch_objects_to_compare(self, sid, did):
|
||||||
|
"""
|
||||||
|
This function will fetch the list of all the event triggers for
|
||||||
|
specified database id.
|
||||||
|
|
||||||
|
:param sid: Server Id
|
||||||
|
:param did: Database Id
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
res = dict()
|
||||||
|
sql = render_template("/".join([self.template_path,
|
||||||
|
'properties.sql']))
|
||||||
|
status, rset = self.conn.execute_2darray(sql)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=rset)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
status, data = self._fetch_properties(did, row['oid'])
|
||||||
|
if status:
|
||||||
|
res[row['name']] = data
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_sql_from_diff(self, **kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to get the DDL/DML statements.
|
||||||
|
:param kwargs:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
gid = kwargs.get('gid')
|
||||||
|
sid = kwargs.get('sid')
|
||||||
|
did = kwargs.get('did')
|
||||||
|
oid = kwargs.get('oid')
|
||||||
|
data = kwargs.get('data', None)
|
||||||
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
sql, name = self.get_sql(data=data, lid=oid)
|
||||||
|
else:
|
||||||
|
if drop_sql:
|
||||||
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
|
lid=oid, only_sql=True)
|
||||||
|
else:
|
||||||
|
sql = self.sql(gid=gid, sid=sid, did=did, lid=oid,
|
||||||
|
json_resp=False)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
SchemaDiffRegistry(blueprint.node_type, LanguageView, 'Database')
|
||||||
LanguageView.register_node_view(blueprint)
|
LanguageView.register_node_view(blueprint)
|
||||||
|
|||||||
@@ -4,5 +4,5 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{# ============= Drop the language ============= #}
|
{# ============= Drop the language ============= #}
|
||||||
{% if lname %}
|
{% if lname %}
|
||||||
DROP LANGUAGE {{ conn|qtIdent(lname) }} {% if cascade %}CASCADE{% endif%};
|
DROP LANGUAGE {{ conn|qtIdent(lname) }}{% if cascade %} CASCADE{% endif%};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -1,6 +1,28 @@
|
|||||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||||
{% import 'macros/security.macros' as SECLABEL %}
|
{% import 'macros/security.macros' as SECLABEL %}
|
||||||
{% if data %}
|
{% if data %}
|
||||||
|
{# ============= Check for Schema Diff Tool ============= #}
|
||||||
|
{% if (data.trusted and data.trusted != o_data.trusted) or (data.lanproc and data.lanproc != o_data.lanproc) or (data.laninl and data.laninl != o_data.laninl) or (data.lanval and data.lanval != o_data.lanval) %}
|
||||||
|
-- WARNING:
|
||||||
|
-- We have found the difference in either of TRUSTED, HANDLER, INLINE or VALIDATOR,
|
||||||
|
-- so we need to drop the existing language first and re-create it.
|
||||||
|
DROP LANGUAGE {{ conn|qtIdent(o_data.name) }} CASCADE;
|
||||||
|
|
||||||
|
{% if data.trusted is defined %}{% set tmp_trusted = data.trusted %}{% else %}{% set tmp_trusted = o_data.trusted %}{% endif %}
|
||||||
|
{% if data.lanproc is defined %}{% set tmp_lanproc = data.lanproc %}{% else %}{% set tmp_lanproc = o_data.lanproc %}{% endif %}
|
||||||
|
{% if data.laninl is defined %}{% set tmp_laninl = data.laninl %}{% else %}{% set tmp_laninl = o_data.laninl %}{% endif %}
|
||||||
|
{% if data.lanval is defined %}{% set tmp_lanval = data.lanval %}{% else %}{% set tmp_lanval = o_data.lanval %}{% endif %}
|
||||||
|
CREATE{% if tmp_trusted %} TRUSTED{% endif %} PROCEDURAL LANGUAGE {{ conn|qtIdent(o_data.name) }}
|
||||||
|
{% if tmp_lanproc %}
|
||||||
|
HANDLER {{ conn|qtIdent(tmp_lanproc) }}
|
||||||
|
{% endif %}
|
||||||
|
{% if tmp_laninl %}
|
||||||
|
INLINE {{ conn|qtIdent(tmp_laninl) }}
|
||||||
|
{% endif %}
|
||||||
|
{% if tmp_lanval %}
|
||||||
|
VALIDATOR {{ conn|qtIdent(tmp_lanval) }}
|
||||||
|
{% endif %};
|
||||||
|
{% endif %}
|
||||||
{# ============= Update language name ============= #}
|
{# ============= Update language name ============= #}
|
||||||
{% if data.name != o_data.name %}
|
{% if data.name != o_data.name %}
|
||||||
ALTER LANGUAGE {{ conn|qtIdent(o_data.name) }}
|
ALTER LANGUAGE {{ conn|qtIdent(o_data.name) }}
|
||||||
|
|||||||
@@ -701,10 +701,8 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
scid: Schema ID
|
scid: Schema ID
|
||||||
coid: Collation ID
|
coid: Collation ID
|
||||||
diff_schema: Target Schema for schema diff
|
|
||||||
json_resp: True then return json response
|
json_resp: True then return json response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
SQL = render_template("/".join([self.template_path,
|
SQL = render_template("/".join([self.template_path,
|
||||||
@@ -720,9 +718,6 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
|
|
||||||
data = res['rows'][0]
|
data = res['rows'][0]
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
|
|
||||||
SQL = render_template("/".join([self.template_path,
|
SQL = render_template("/".join([self.template_path,
|
||||||
self._CREATE_SQL]),
|
self._CREATE_SQL]),
|
||||||
data=data, conn=self.conn)
|
data=data, conn=self.conn)
|
||||||
@@ -821,21 +816,15 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_sql(gid=gid, sid=sid, data=data, scid=scid,
|
sql, name = self.get_sql(gid=gid, sid=sid, data=data, scid=scid,
|
||||||
coid=oid)
|
coid=oid)
|
||||||
else:
|
else:
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, coid=oid, only_sql=True)
|
scid=scid, coid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, coid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, coid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, coid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -723,10 +723,8 @@ AND relkind != 'c'))"""
|
|||||||
did: Database Id
|
did: Database Id
|
||||||
scid: Schema Id
|
scid: Schema Id
|
||||||
doid: Domain Id
|
doid: Domain Id
|
||||||
diff_schema: Target Schema for schema diff
|
|
||||||
json_resp: True then return json response
|
json_resp: True then return json response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
SQL = render_template("/".join([self.template_path,
|
SQL = render_template("/".join([self.template_path,
|
||||||
@@ -742,9 +740,6 @@ AND relkind != 'c'))"""
|
|||||||
|
|
||||||
data = res['rows'][0]
|
data = res['rows'][0]
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
data['basensp'] = diff_schema
|
|
||||||
|
|
||||||
# Get Type Length and Precision
|
# Get Type Length and Precision
|
||||||
data.update(self._parse_type(data['fulltype']))
|
data.update(self._parse_type(data['fulltype']))
|
||||||
|
|
||||||
@@ -954,12 +949,9 @@ AND relkind != 'c'))"""
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_sql(gid=gid, sid=sid, scid=scid,
|
sql, name = self.get_sql(gid=gid, sid=sid, scid=scid,
|
||||||
data=data, doid=oid,
|
data=data, doid=oid,
|
||||||
is_schema_diff=True)
|
is_schema_diff=True)
|
||||||
@@ -967,9 +959,6 @@ AND relkind != 'c'))"""
|
|||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, doid=oid, only_sql=True)
|
scid=scid, doid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, doid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, doid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, doid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -832,10 +832,8 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
did: Database Id
|
did: Database Id
|
||||||
scid: Schema Id
|
scid: Schema Id
|
||||||
foid: Foreign Table Id
|
foid: Foreign Table Id
|
||||||
diff_schema: Target Schema for schema diff
|
|
||||||
json_resp: True then return json response
|
json_resp: True then return json response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
status, data = self._fetch_properties(gid, sid, did, scid, foid,
|
status, data = self._fetch_properties(gid, sid, did, scid, foid,
|
||||||
@@ -846,9 +844,6 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
return gone(
|
return gone(
|
||||||
gettext("The specified foreign table could not be found."))
|
gettext("The specified foreign table could not be found."))
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
data['basensp'] = diff_schema
|
|
||||||
|
|
||||||
col_data = []
|
col_data = []
|
||||||
for c in data['columns']:
|
for c in data['columns']:
|
||||||
if ('inheritedfrom' not in c) or (c['inheritedfrom'] is None):
|
if ('inheritedfrom' not in c) or (c['inheritedfrom'] is None):
|
||||||
@@ -1494,12 +1489,9 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
||||||
data=data, foid=oid,
|
data=data, foid=oid,
|
||||||
is_schema_diff=True)
|
is_schema_diff=True)
|
||||||
@@ -1507,9 +1499,6 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, foid=oid, only_sql=True)
|
scid=scid, foid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, foid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, foid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, foid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -205,6 +205,8 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
'compare': [{'get': 'compare'}, {'get': 'compare'}]
|
'compare': [{'get': 'compare'}, {'get': 'compare'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
keys_to_ignore = ['oid', 'oid-2', 'schema']
|
||||||
|
|
||||||
def _init_(self, **kwargs):
|
def _init_(self, **kwargs):
|
||||||
self.conn = None
|
self.conn = None
|
||||||
self.template_path = None
|
self.template_path = None
|
||||||
@@ -903,10 +905,8 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
:param did: database id
|
:param did: database id
|
||||||
:param scid: schema id
|
:param scid: schema id
|
||||||
:param cfgid: FTS Configuration id
|
:param cfgid: FTS Configuration id
|
||||||
:param diff_schema: Target Schema for schema diff
|
|
||||||
:param json_resp: True then return json response
|
:param json_resp: True then return json response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -932,22 +932,6 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
"FTS Configuration node.")
|
"FTS Configuration node.")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Used for schema diff tool
|
|
||||||
if diff_schema:
|
|
||||||
data = {'schema': scid}
|
|
||||||
# Fetch schema name from schema oid
|
|
||||||
sql = render_template("/".join([self.template_path,
|
|
||||||
self._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, diff_schema)
|
|
||||||
|
|
||||||
if not json_resp:
|
if not json_resp:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@@ -1032,21 +1016,15 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
||||||
data=data, cfgid=oid)
|
data=data, cfgid=oid)
|
||||||
else:
|
else:
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, cfgid=oid, only_sql=True)
|
scid=scid, cfgid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, cfgid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, cfgid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, cfgid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -192,6 +192,8 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
{'get': 'fetch_templates'}]
|
{'get': 'fetch_templates'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
keys_to_ignore = ['oid', 'oid-2', 'schema']
|
||||||
|
|
||||||
def _init_(self, **kwargs):
|
def _init_(self, **kwargs):
|
||||||
self.conn = None
|
self.conn = None
|
||||||
self.template_path = None
|
self.template_path = None
|
||||||
@@ -798,10 +800,8 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
:param did: database id
|
:param did: database id
|
||||||
:param scid: schema id
|
:param scid: schema id
|
||||||
:param dcid: FTS Dictionary id
|
:param dcid: FTS Dictionary id
|
||||||
:param diff_schema: Target Schema for schema diff
|
|
||||||
:param json_resp: True then return json response
|
:param json_resp: True then return json response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
@@ -847,9 +847,6 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
# Replace schema oid with schema name
|
# Replace schema oid with schema name
|
||||||
res['rows'][0]['schema'] = schema
|
res['rows'][0]['schema'] = schema
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
res['rows'][0]['schema'] = diff_schema
|
|
||||||
|
|
||||||
sql = render_template("/".join([self.template_path,
|
sql = render_template("/".join([self.template_path,
|
||||||
self._CREATE_SQL]),
|
self._CREATE_SQL]),
|
||||||
data=res['rows'][0],
|
data=res['rows'][0],
|
||||||
@@ -943,21 +940,15 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
||||||
data=data, dcid=oid)
|
data=data, dcid=oid)
|
||||||
else:
|
else:
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, dcid=oid, only_sql=True)
|
scid=scid, dcid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, dcid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, dcid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, dcid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -201,6 +201,8 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
{'get': 'headline_functions'}]
|
{'get': 'headline_functions'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
keys_to_ignore = ['oid', 'oid-2', 'schema']
|
||||||
|
|
||||||
def _init_(self, **kwargs):
|
def _init_(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
Method is used to initialize the FtsParserView and it's base view.
|
Method is used to initialize the FtsParserView and it's base view.
|
||||||
@@ -848,10 +850,8 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
:param did: database id
|
:param did: database id
|
||||||
:param scid: schema id
|
:param scid: schema id
|
||||||
:param pid: fts tempate id
|
:param pid: fts tempate id
|
||||||
:param diff_schema: Target Schema for schema diff
|
|
||||||
:param json_resp: True then return json response
|
:param json_resp: True then return json response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -878,22 +878,6 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Used for schema diff tool
|
|
||||||
if diff_schema:
|
|
||||||
data = {'schema': scid}
|
|
||||||
# Fetch schema name from schema oid
|
|
||||||
sql = render_template("/".join([self.template_path,
|
|
||||||
self._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, diff_schema)
|
|
||||||
|
|
||||||
if not json_resp:
|
if not json_resp:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@@ -978,21 +962,15 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
||||||
data=data, pid=oid)
|
data=data, pid=oid)
|
||||||
else:
|
else:
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, pid=oid, only_sql=True)
|
scid=scid, pid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -187,6 +187,8 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
'get_init': [{'get': 'get_init'}, {'get': 'get_init'}]
|
'get_init': [{'get': 'get_init'}, {'get': 'get_init'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
keys_to_ignore = ['oid', 'oid-2', 'schema']
|
||||||
|
|
||||||
def _init_(self, **kwargs):
|
def _init_(self, **kwargs):
|
||||||
self.conn = None
|
self.conn = None
|
||||||
self.template_path = None
|
self.template_path = None
|
||||||
@@ -735,10 +737,8 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
:param did: database id
|
:param did: database id
|
||||||
:param scid: schema id
|
:param scid: schema id
|
||||||
:param tid: fts tempate id
|
:param tid: fts tempate id
|
||||||
:param diff_schema: Target Schema for schema diff
|
|
||||||
:param json_resp: True then return json response
|
:param json_resp: True then return json response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
@@ -762,22 +762,6 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
"FTS Template node.")
|
"FTS Template node.")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Used for schema diff tool
|
|
||||||
if diff_schema:
|
|
||||||
data = {'schema': scid}
|
|
||||||
# Fetch schema name from schema oid
|
|
||||||
sql = render_template("/".join([self.template_path,
|
|
||||||
self._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, diff_schema)
|
|
||||||
|
|
||||||
if not json_resp:
|
if not json_resp:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@@ -858,21 +842,15 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
sql, name = self.get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
||||||
data=data, tid=oid)
|
data=data, tid=oid)
|
||||||
else:
|
else:
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, tid=oid, only_sql=True)
|
scid=scid, tid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -221,7 +221,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
|||||||
|
|
||||||
keys_to_ignore = ['oid', 'proowner', 'typnsp', 'xmin', 'prokind',
|
keys_to_ignore = ['oid', 'proowner', 'typnsp', 'xmin', 'prokind',
|
||||||
'proisagg', 'pronamespace', 'proargdefaults',
|
'proisagg', 'pronamespace', 'proargdefaults',
|
||||||
'prorettype', 'proallargtypes', 'proacl', 'oid-2']
|
'prorettype', 'proallargtypes', 'proacl', 'oid-2',
|
||||||
|
'prolang']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def required_args(self):
|
def required_args(self):
|
||||||
@@ -1085,8 +1086,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
|||||||
did: Database Id
|
did: Database Id
|
||||||
scid: Schema Id
|
scid: Schema Id
|
||||||
fnid: Function Id
|
fnid: Function Id
|
||||||
|
json_resp:
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
resp_data = self._fetch_properties(gid, sid, did, scid, fnid)
|
resp_data = self._fetch_properties(gid, sid, did, scid, fnid)
|
||||||
@@ -1131,8 +1132,6 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
|||||||
status, res = self.conn.execute_2darray(sql)
|
status, res = self.conn.execute_2darray(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
elif diff_schema:
|
|
||||||
res['rows'][0]['nspname'] = diff_schema
|
|
||||||
|
|
||||||
# Add newline and tab before each argument to format
|
# Add newline and tab before each argument to format
|
||||||
name_with_default_args = self.qtIdent(
|
name_with_default_args = self.qtIdent(
|
||||||
@@ -1170,9 +1169,6 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
|||||||
status, res = self.conn.execute_2darray(sql)
|
status, res = self.conn.execute_2darray(sql)
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
elif diff_schema:
|
|
||||||
res['rows'][0]['nspname'] = diff_schema
|
|
||||||
resp_data['pronamespace'] = diff_schema
|
|
||||||
|
|
||||||
# Add newline and tab before each argument to format
|
# Add newline and tab before each argument to format
|
||||||
name_with_default_args = self.qtIdent(
|
name_with_default_args = self.qtIdent(
|
||||||
@@ -1823,12 +1819,9 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
status, sql = self._get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
status, sql = self._get_sql(gid=gid, sid=sid, did=did, scid=scid,
|
||||||
data=data, fnid=oid, is_sql=False,
|
data=data, fnid=oid, is_sql=False,
|
||||||
is_schema_diff=True)
|
is_schema_diff=True)
|
||||||
@@ -1842,9 +1835,6 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
|||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, fnid=oid, only_sql=True)
|
scid=scid, fnid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, fnid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, fnid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, fnid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import re
|
|||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
import simplejson as json
|
import simplejson as json
|
||||||
from flask import render_template, request, jsonify
|
from flask import render_template, make_response, request, jsonify
|
||||||
from flask_babelex import gettext as _
|
from flask_babelex import gettext as _
|
||||||
|
|
||||||
import pgadmin.browser.server_groups.servers.databases as database
|
import pgadmin.browser.server_groups.servers.databases as database
|
||||||
@@ -584,15 +584,10 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
data = kwargs.get('data')
|
data = kwargs.get('data')
|
||||||
pkgid = kwargs.get('pkgid', None)
|
pkgid = kwargs.get('pkgid', None)
|
||||||
sqltab = kwargs.get('sqltab', False)
|
sqltab = kwargs.get('sqltab', False)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
is_schema_diff = kwargs.get('is_schema_diff', None)
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
else:
|
|
||||||
data['schema'] = self.schema
|
|
||||||
|
|
||||||
if pkgid is not None and not sqltab:
|
if pkgid is not None and not sqltab:
|
||||||
return self.get_sql_with_pkgid(scid, pkgid, data, diff_schema)
|
return self.get_sql_with_pkgid(scid, pkgid, data, is_schema_diff)
|
||||||
else:
|
else:
|
||||||
# To format privileges coming from client
|
# To format privileges coming from client
|
||||||
if 'pkgacl' in data:
|
if 'pkgacl' in data:
|
||||||
@@ -618,7 +613,15 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
data[key]['deleted'] = parse_priv_to_db(
|
data[key]['deleted'] = parse_priv_to_db(
|
||||||
data[key]['deleted'], self.acl)
|
data[key]['deleted'], self.acl)
|
||||||
|
|
||||||
def get_sql_with_pkgid(self, scid, pkgid, data, diff_schema):
|
def get_sql_with_pkgid(self, scid, pkgid, data, is_schema_diff):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param scid:
|
||||||
|
:param pkgid:
|
||||||
|
:param data:
|
||||||
|
:param is_schema_diff:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
required_args = [
|
required_args = [
|
||||||
u'name'
|
u'name'
|
||||||
]
|
]
|
||||||
@@ -666,7 +669,7 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
sql = render_template("/".join([self.template_path,
|
sql = render_template("/".join([self.template_path,
|
||||||
self._UPDATE_SQL]),
|
self._UPDATE_SQL]),
|
||||||
data=data, o_data=old_data, conn=self.conn,
|
data=data, o_data=old_data, conn=self.conn,
|
||||||
is_schema_diff=diff_schema)
|
is_schema_diff=is_schema_diff)
|
||||||
return sql, data['name'] if 'name' in data else old_data['name']
|
return sql, data['name'] if 'name' in data else old_data['name']
|
||||||
|
|
||||||
@check_precondition(action="sql")
|
@check_precondition(action="sql")
|
||||||
@@ -680,10 +683,10 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
scid: Schema ID
|
scid: Schema ID
|
||||||
pkgid: Package ID
|
pkgid: Package ID
|
||||||
diff_schema: Schema diff target schema name
|
is_schema_diff:
|
||||||
json_resp: json response or plain text response
|
json_resp: json response or plain text response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
is_schema_diff = kwargs.get('is_schema_diff', None)
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -717,8 +720,11 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
res['rows'][0].setdefault(row['deftype'], []).append(priv)
|
res['rows'][0].setdefault(row['deftype'], []).append(priv)
|
||||||
|
|
||||||
result = res['rows'][0]
|
result = res['rows'][0]
|
||||||
|
|
||||||
sql, name = self.getSQL(data=result, scid=scid, pkgid=pkgid,
|
sql, name = self.getSQL(data=result, scid=scid, pkgid=pkgid,
|
||||||
sqltab=True, diff_schema=diff_schema)
|
sqltab=True,
|
||||||
|
is_schema_diff=is_schema_diff)
|
||||||
|
|
||||||
# Most probably this is due to error
|
# Most probably this is due to error
|
||||||
if not isinstance(sql, str):
|
if not isinstance(sql, str):
|
||||||
return sql
|
return sql
|
||||||
@@ -841,23 +847,17 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.getSQL(data=data, scid=scid, pkgid=oid)
|
sql, name = self.getSQL(data=data, scid=scid, pkgid=oid)
|
||||||
else:
|
else:
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, pkgid=oid, only_sql=True)
|
scid=scid, pkgid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pkgid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pkgid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, pkgid=oid,
|
||||||
json_resp=False)
|
is_schema_diff=True, json_resp=False)
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -699,10 +699,8 @@ class SequenceView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
scid: Schema ID
|
scid: Schema ID
|
||||||
seid: Sequence ID
|
seid: Sequence ID
|
||||||
diff_schema: Schema diff target schema name
|
|
||||||
json_resp: json response or plain text response
|
json_resp: json response or plain text response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
@@ -734,9 +732,6 @@ class SequenceView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
|
|
||||||
result = res['rows'][0]
|
result = res['rows'][0]
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
result['schema'] = diff_schema
|
|
||||||
|
|
||||||
result = self._formatter(result, scid, seid)
|
result = self._formatter(result, scid, seid)
|
||||||
sql, name = self.get_SQL(gid, sid, did, result, scid)
|
sql, name = self.get_SQL(gid, sid, did, result, scid)
|
||||||
# Most probably this is due to error
|
# Most probably this is due to error
|
||||||
@@ -952,20 +947,14 @@ class SequenceView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_SQL(gid, sid, did, data, scid, oid)
|
sql, name = self.get_SQL(gid, sid, did, data, scid, oid)
|
||||||
else:
|
else:
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, seid=oid, only_sql=True)
|
scid=scid, seid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, seid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, seid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, seid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -670,10 +670,8 @@ class SynonymView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
scid: Schema ID
|
scid: Schema ID
|
||||||
syid: Synonym ID
|
syid: Synonym ID
|
||||||
diff_schema:
|
|
||||||
json_resp:
|
json_resp:
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
SQL = render_template("/".join([self.template_path,
|
SQL = render_template("/".join([self.template_path,
|
||||||
@@ -690,9 +688,6 @@ class SynonymView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
gettext('The specified synonym could not be found.')
|
gettext('The specified synonym could not be found.')
|
||||||
)
|
)
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
|
|
||||||
SQL = render_template("/".join([self.template_path,
|
SQL = render_template("/".join([self.template_path,
|
||||||
self._CREATE_SQL]),
|
self._CREATE_SQL]),
|
||||||
data=data, conn=self.conn, comment=True)
|
data=data, conn=self.conn, comment=True)
|
||||||
@@ -781,21 +776,14 @@ class SynonymView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_sql(gid, sid, data, scid, oid)
|
sql, name = self.get_sql(gid, sid, data, scid, oid)
|
||||||
else:
|
else:
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, syid=oid, only_sql=True)
|
scid=scid, syid=oid, only_sql=True)
|
||||||
|
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, syid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, syid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, syid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -1249,8 +1249,6 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings,
|
|||||||
tid = kwargs['tid']
|
tid = kwargs['tid']
|
||||||
diff_data = kwargs['diff_data'] if 'diff_data' in kwargs else None
|
diff_data = kwargs['diff_data'] if 'diff_data' in kwargs else None
|
||||||
json_resp = kwargs['json_resp'] if 'json_resp' in kwargs else True
|
json_resp = kwargs['json_resp'] if 'json_resp' in kwargs else True
|
||||||
diff_schema = kwargs['diff_schema'] if 'diff_schema' in kwargs else\
|
|
||||||
None
|
|
||||||
|
|
||||||
if diff_data:
|
if diff_data:
|
||||||
return self._fetch_sql(did, scid, tid, diff_data, json_resp)
|
return self._fetch_sql(did, scid, tid, diff_data, json_resp)
|
||||||
@@ -1273,9 +1271,6 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings,
|
|||||||
if status:
|
if status:
|
||||||
data = res['rows'][0]
|
data = res['rows'][0]
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
|
|
||||||
sql, partition_sql = BaseTableView.get_reverse_engineered_sql(
|
sql, partition_sql = BaseTableView.get_reverse_engineered_sql(
|
||||||
self, did=did, scid=scid, tid=tid, main_sql=main_sql,
|
self, did=did, scid=scid, tid=tid, main_sql=main_sql,
|
||||||
data=data, json_resp=json_resp)
|
data=data, json_resp=json_resp)
|
||||||
@@ -1662,13 +1657,6 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings,
|
|||||||
:param tid: Table Id
|
:param tid: Table Id
|
||||||
:return: Table dataset
|
:return: Table dataset
|
||||||
"""
|
"""
|
||||||
sub_modules = ['index', 'rule', 'trigger']
|
|
||||||
if self.manager.server_type == 'ppas' and \
|
|
||||||
self.manager.version >= 120000:
|
|
||||||
sub_modules.append('compound_trigger')
|
|
||||||
|
|
||||||
if self.manager.version >= 90500:
|
|
||||||
sub_modules.append('row_security_policy')
|
|
||||||
|
|
||||||
if tid:
|
if tid:
|
||||||
status, data = self._fetch_properties(did, scid, tid)
|
status, data = self._fetch_properties(did, scid, tid)
|
||||||
@@ -1704,16 +1692,15 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings,
|
|||||||
# Get sub module data of a specified table for object
|
# Get sub module data of a specified table for object
|
||||||
# comparison
|
# comparison
|
||||||
self._get_sub_module_data_for_compare(sid, did, scid, data,
|
self._get_sub_module_data_for_compare(sid, did, scid, data,
|
||||||
row, sub_modules)
|
row)
|
||||||
res[row['name']] = data
|
res[row['name']] = data
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _get_sub_module_data_for_compare(self, sid, did, scid, data,
|
def _get_sub_module_data_for_compare(self, sid, did, scid, data, row):
|
||||||
row, sub_modules):
|
|
||||||
# Get sub module data of a specified table for object
|
# Get sub module data of a specified table for object
|
||||||
# comparison
|
# comparison
|
||||||
for module in sub_modules:
|
for module in self.tables_sub_modules:
|
||||||
module_view = SchemaDiffRegistry.get_node_view(module)
|
module_view = SchemaDiffRegistry.get_node_view(module)
|
||||||
if module_view.blueprint.server_type is None or \
|
if module_view.blueprint.server_type is None or \
|
||||||
self.manager.server_type in \
|
self.manager.server_type in \
|
||||||
@@ -1723,6 +1710,76 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings,
|
|||||||
oid=None)
|
oid=None)
|
||||||
data[module] = sub_data
|
data[module] = sub_data
|
||||||
|
|
||||||
|
def get_submodule_template_path(self, module_name):
|
||||||
|
"""
|
||||||
|
This function is used to get the template path based on module name.
|
||||||
|
:param module_name:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
template_path = None
|
||||||
|
if module_name == 'index':
|
||||||
|
template_path = self.index_template_path
|
||||||
|
elif module_name == 'trigger':
|
||||||
|
template_path = self.trigger_template_path
|
||||||
|
elif module_name == 'rule':
|
||||||
|
template_path = self.rules_template_path
|
||||||
|
elif module_name == 'compound_trigger':
|
||||||
|
template_path = self.compound_trigger_template_path
|
||||||
|
elif module_name == 'row_security_policy':
|
||||||
|
template_path = self.row_security_policies_template_path
|
||||||
|
|
||||||
|
return template_path
|
||||||
|
|
||||||
|
@BaseTableView.check_precondition
|
||||||
|
def get_table_submodules_dependencies(self, **kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to get the dependencies of table and it's
|
||||||
|
submodules.
|
||||||
|
:param kwargs:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
tid = kwargs['tid']
|
||||||
|
table_dependencies = []
|
||||||
|
table_deps = self.get_dependencies(self.conn, tid, where=None,
|
||||||
|
show_system_objects=None,
|
||||||
|
is_schema_diff=True)
|
||||||
|
if len(table_deps) > 0:
|
||||||
|
table_dependencies.extend(table_deps)
|
||||||
|
|
||||||
|
# Fetch foreign key referenced table which is considered as
|
||||||
|
# dependency.
|
||||||
|
status, fkey_deps = fkey_utils.get_fkey_dependencies(self.conn, tid)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=fkey_deps)
|
||||||
|
|
||||||
|
if len(fkey_deps) > 0:
|
||||||
|
table_dependencies.extend(fkey_deps)
|
||||||
|
|
||||||
|
# Iterate all the submodules of the table and fetch the dependencies.
|
||||||
|
for module in self.tables_sub_modules:
|
||||||
|
module_view = SchemaDiffRegistry.get_node_view(module)
|
||||||
|
template_path = self.get_submodule_template_path(module)
|
||||||
|
|
||||||
|
SQL = render_template("/".join([template_path,
|
||||||
|
'nodes.sql']), tid=tid)
|
||||||
|
status, rset = self.conn.execute_2darray(SQL)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=rset)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
result = module_view.get_dependencies(
|
||||||
|
self.conn, row['oid'], where=None,
|
||||||
|
show_system_objects=None, is_schema_diff=True)
|
||||||
|
if len(result) > 0:
|
||||||
|
table_dependencies.extend(result)
|
||||||
|
|
||||||
|
# Remove the same table from the dependency list
|
||||||
|
for item in table_dependencies:
|
||||||
|
if 'oid' in item and item['oid'] == tid:
|
||||||
|
table_dependencies.remove(item)
|
||||||
|
|
||||||
|
return table_dependencies
|
||||||
|
|
||||||
|
|
||||||
SchemaDiffRegistry(blueprint.node_type, TableView)
|
SchemaDiffRegistry(blueprint.node_type, TableView)
|
||||||
TableView.register_node_view(blueprint)
|
TableView.register_node_view(blueprint)
|
||||||
|
|||||||
@@ -887,7 +887,6 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
tid = kwargs.get('tid')
|
tid = kwargs.get('tid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
@@ -927,22 +926,17 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
data['columns'] = self._column_details(tid, columns)
|
data['columns'] = self._column_details(tid, columns)
|
||||||
|
|
||||||
data = trigger_definition(data)
|
data = trigger_definition(data)
|
||||||
|
sql = self._check_and_add_compound_trigger(tid, data)
|
||||||
sql = self._check_and_add_compound_trigger(tid, data,
|
|
||||||
diff_schema)
|
|
||||||
|
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
def _check_and_add_compound_trigger(self, tid, data, diff_schema):
|
def _check_and_add_compound_trigger(self, tid, data):
|
||||||
"""
|
"""
|
||||||
This get compound trigger and check for disable.
|
This get compound trigger and check for disable.
|
||||||
:param tid: Table Id.
|
:param tid: Table Id.
|
||||||
:param data: Data.
|
:param data: Data.
|
||||||
:param diff_schema: schema diff check.
|
:param diff_schema: schema diff check.
|
||||||
"""
|
"""
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
|
|
||||||
sql, name = compound_trigger_utils.get_sql(self.conn,
|
sql, name = compound_trigger_utils.get_sql(self.conn,
|
||||||
data,
|
data,
|
||||||
tid,
|
tid,
|
||||||
@@ -1007,7 +1001,6 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
tgt_params = kwargs.get('target_params')
|
tgt_params = kwargs.get('target_params')
|
||||||
source = kwargs.get('source')
|
source = kwargs.get('source')
|
||||||
target = kwargs.get('target')
|
target = kwargs.get('target')
|
||||||
target_schema = kwargs.get('target_schema')
|
|
||||||
comp_status = kwargs.get('comp_status')
|
comp_status = kwargs.get('comp_status')
|
||||||
|
|
||||||
diff = ''
|
diff = ''
|
||||||
@@ -1017,8 +1010,7 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
did=src_params['did'],
|
did=src_params['did'],
|
||||||
scid=src_params['scid'],
|
scid=src_params['scid'],
|
||||||
tid=src_params['tid'],
|
tid=src_params['tid'],
|
||||||
oid=source['oid'],
|
oid=source['oid'])
|
||||||
diff_schema=target_schema)
|
|
||||||
elif comp_status == 'target_only':
|
elif comp_status == 'target_only':
|
||||||
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
|
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
|
||||||
sid=tgt_params['sid'],
|
sid=tgt_params['sid'],
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ from pgadmin.utils.ajax import internal_server_error
|
|||||||
from pgadmin.utils.exception import ObjectGone, ExecuteError
|
from pgadmin.utils.exception import ObjectGone, ExecuteError
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
FKEY_PROPERTIES_SQL = 'properties.sql'
|
||||||
|
|
||||||
|
|
||||||
def get_template_path(f):
|
def get_template_path(f):
|
||||||
"""
|
"""
|
||||||
@@ -47,7 +49,7 @@ def get_foreign_keys(conn, tid, fkid=None, template_path=None):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
sql = render_template("/".join(
|
sql = render_template("/".join(
|
||||||
[template_path, 'properties.sql']), tid=tid, cid=fkid)
|
[template_path, FKEY_PROPERTIES_SQL]), tid=tid, cid=fkid)
|
||||||
|
|
||||||
status, result = conn.execute_dict(sql)
|
status, result = conn.execute_dict(sql)
|
||||||
if not status:
|
if not status:
|
||||||
@@ -286,7 +288,7 @@ def _get_properties_for_fk_const(tid, fkid, data, template_path, conn):
|
|||||||
conn: Connection.
|
conn: Connection.
|
||||||
"""
|
"""
|
||||||
name = data['name'] if 'name' in data else None
|
name = data['name'] if 'name' in data else None
|
||||||
sql = render_template("/".join([template_path, 'properties.sql']),
|
sql = render_template("/".join([template_path, FKEY_PROPERTIES_SQL]),
|
||||||
tid=tid, cid=fkid)
|
tid=tid, cid=fkid)
|
||||||
status, res = conn.execute_dict(sql)
|
status, res = conn.execute_dict(sql)
|
||||||
if not status:
|
if not status:
|
||||||
@@ -357,3 +359,29 @@ def _checks_for_schema_diff(table, schema, data):
|
|||||||
|
|
||||||
if 'remote_table' not in data:
|
if 'remote_table' not in data:
|
||||||
data['remote_table'] = None
|
data['remote_table'] = None
|
||||||
|
|
||||||
|
|
||||||
|
@get_template_path
|
||||||
|
def get_fkey_dependencies(conn, tid, template_path=None):
|
||||||
|
"""
|
||||||
|
This function is used to get the references table of all the foreign
|
||||||
|
keys of the given table.
|
||||||
|
|
||||||
|
:param conn:
|
||||||
|
:param tid:
|
||||||
|
:param template_path:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
deps = []
|
||||||
|
sql = render_template("/".join(
|
||||||
|
[template_path, FKEY_PROPERTIES_SQL]), tid=tid)
|
||||||
|
|
||||||
|
status, result = conn.execute_dict(sql)
|
||||||
|
if not status:
|
||||||
|
return status, internal_server_error(errormsg=result)
|
||||||
|
|
||||||
|
for fk in result['rows']:
|
||||||
|
ref_name = fk['refnsp'] + '.' + fk['reftab']
|
||||||
|
deps.append({'type': 'table', 'name': ref_name})
|
||||||
|
|
||||||
|
return True, deps
|
||||||
|
|||||||
@@ -849,7 +849,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
tid = kwargs.get('tid')
|
tid = kwargs.get('tid')
|
||||||
idx = kwargs.get('idx')
|
idx = kwargs.get('idx')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
create_mode = kwargs.get('create_mode', None)
|
||||||
drop_req = kwargs.get('drop_req', False)
|
drop_req = kwargs.get('drop_req', False)
|
||||||
sql = ''
|
sql = ''
|
||||||
|
|
||||||
@@ -864,10 +864,9 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
|
|
||||||
sql = sql.strip('\n').strip(' ')
|
sql = sql.strip('\n').strip(' ')
|
||||||
|
|
||||||
elif diff_schema:
|
elif create_mode:
|
||||||
schema = diff_schema
|
|
||||||
sql = index_utils.get_reverse_engineered_sql(
|
sql = index_utils.get_reverse_engineered_sql(
|
||||||
self.conn, schema=schema,
|
self.conn, schema=self.schema,
|
||||||
table=self.table, did=did, tid=tid, idx=idx,
|
table=self.table, did=did, tid=tid, idx=idx,
|
||||||
datlastsysoid=self.datlastsysoid,
|
datlastsysoid=self.datlastsysoid,
|
||||||
template_path=None, with_header=False)
|
template_path=None, with_header=False)
|
||||||
@@ -1077,7 +1076,6 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
tgt_params = kwargs.get('target_params')
|
tgt_params = kwargs.get('target_params')
|
||||||
source = kwargs.get('source')
|
source = kwargs.get('source')
|
||||||
target = kwargs.get('target')
|
target = kwargs.get('target')
|
||||||
target_schema = kwargs.get('target_schema')
|
|
||||||
comp_status = kwargs.get('comp_status')
|
comp_status = kwargs.get('comp_status')
|
||||||
|
|
||||||
diff = ''
|
diff = ''
|
||||||
@@ -1087,7 +1085,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid=src_params['scid'],
|
scid=src_params['scid'],
|
||||||
tid=src_params['tid'],
|
tid=src_params['tid'],
|
||||||
idx=source['oid'],
|
idx=source['oid'],
|
||||||
diff_schema=target_schema)
|
create_mode=True)
|
||||||
elif comp_status == 'target_only':
|
elif comp_status == 'target_only':
|
||||||
diff = self.delete(gid=1, sid=tgt_params['sid'],
|
diff = self.delete(gid=1, sid=tgt_params['sid'],
|
||||||
did=tgt_params['did'], scid=tgt_params['scid'],
|
did=tgt_params['did'], scid=tgt_params['scid'],
|
||||||
@@ -1113,7 +1111,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid=src_params['scid'],
|
scid=src_params['scid'],
|
||||||
tid=src_params['tid'],
|
tid=src_params['tid'],
|
||||||
idx=source['oid'],
|
idx=source['oid'],
|
||||||
diff_schema=target_schema,
|
create_mode=True,
|
||||||
drop_req=True)
|
drop_req=True)
|
||||||
else:
|
else:
|
||||||
diff = self.get_sql_from_index_diff(sid=tgt_params['sid'],
|
diff = self.get_sql_from_index_diff(sid=tgt_params['sid'],
|
||||||
|
|||||||
@@ -606,7 +606,6 @@ class RowSecurityView(PGChildNodeView):
|
|||||||
tid = kwargs.get('tid')
|
tid = kwargs.get('tid')
|
||||||
oid = kwargs.get('plid')
|
oid = kwargs.get('plid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_req = kwargs.get('drop_req', False)
|
drop_req = kwargs.get('drop_req', False)
|
||||||
|
|
||||||
sql = ''
|
sql = ''
|
||||||
@@ -619,11 +618,9 @@ class RowSecurityView(PGChildNodeView):
|
|||||||
|
|
||||||
sql = sql.strip('\n').strip(' ')
|
sql = sql.strip('\n').strip(' ')
|
||||||
|
|
||||||
elif diff_schema:
|
else:
|
||||||
schema = diff_schema
|
|
||||||
|
|
||||||
sql = row_security_policies_utils.get_reverse_engineered_sql(
|
sql = row_security_policies_utils.get_reverse_engineered_sql(
|
||||||
self.conn, schema=schema, table=self.table, scid=scid,
|
self.conn, schema=self.schema, table=self.table, scid=scid,
|
||||||
plid=oid, datlastsysoid=self.datlastsysoid, with_header=False)
|
plid=oid, datlastsysoid=self.datlastsysoid, with_header=False)
|
||||||
|
|
||||||
drop_sql = ''
|
drop_sql = ''
|
||||||
@@ -684,7 +681,6 @@ class RowSecurityView(PGChildNodeView):
|
|||||||
tgt_params = kwargs.get('target_params')
|
tgt_params = kwargs.get('target_params')
|
||||||
source = kwargs.get('source')
|
source = kwargs.get('source')
|
||||||
target = kwargs.get('target')
|
target = kwargs.get('target')
|
||||||
target_schema = kwargs.get('target_schema')
|
|
||||||
comp_status = kwargs.get('comp_status')
|
comp_status = kwargs.get('comp_status')
|
||||||
|
|
||||||
diff = ''
|
diff = ''
|
||||||
@@ -694,8 +690,7 @@ class RowSecurityView(PGChildNodeView):
|
|||||||
did=src_params['did'],
|
did=src_params['did'],
|
||||||
scid=src_params['scid'],
|
scid=src_params['scid'],
|
||||||
tid=src_params['tid'],
|
tid=src_params['tid'],
|
||||||
plid=source['oid'],
|
plid=source['oid'])
|
||||||
diff_schema=target_schema)
|
|
||||||
elif comp_status == 'target_only':
|
elif comp_status == 'target_only':
|
||||||
diff = self.delete(gid=1,
|
diff = self.delete(gid=1,
|
||||||
sid=tgt_params['sid'],
|
sid=tgt_params['sid'],
|
||||||
@@ -722,8 +717,7 @@ class RowSecurityView(PGChildNodeView):
|
|||||||
did=src_params['did'],
|
did=src_params['did'],
|
||||||
scid=src_params['scid'],
|
scid=src_params['scid'],
|
||||||
tid=src_params['tid'],
|
tid=src_params['tid'],
|
||||||
plid=source['oid'],
|
plid=source['oid'])
|
||||||
diff_schema=target_schema)
|
|
||||||
return delete_sql + diff
|
return delete_sql + diff
|
||||||
|
|
||||||
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
|
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
|
||||||
|
|||||||
@@ -531,8 +531,6 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
tid = kwargs.get('tid')
|
tid = kwargs.get('tid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
source_schema = kwargs.get('source_schema', None)
|
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
@@ -551,43 +549,19 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
)
|
)
|
||||||
res_data = parse_rule_definition(res)
|
res_data = parse_rule_definition(res)
|
||||||
|
|
||||||
sql = ''
|
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if source_schema and 'statements' in data:
|
|
||||||
# Replace the source schema with the target schema
|
|
||||||
data['statements'] = data['statements'].replace(
|
|
||||||
source_schema, diff_schema)
|
|
||||||
old_data = res_data
|
old_data = res_data
|
||||||
sql = render_template(
|
sql = render_template(
|
||||||
"/".join([self.template_path, self._UPDATE_SQL]),
|
"/".join([self.template_path, self._UPDATE_SQL]),
|
||||||
data=data, o_data=old_data
|
data=data, o_data=old_data
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
RuleView._check_schema_diff(diff_schema, res_data)
|
|
||||||
|
|
||||||
sql = render_template("/".join(
|
sql = render_template("/".join(
|
||||||
[self.template_path, self._CREATE_SQL]),
|
[self.template_path, self._CREATE_SQL]),
|
||||||
data=res_data, display_comments=True)
|
data=res_data, display_comments=True)
|
||||||
|
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _check_schema_diff(diff_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 diff_schema:
|
|
||||||
if 'statements' in res_data:
|
|
||||||
# Replace the source schema with the target schema
|
|
||||||
res_data['statements'] = \
|
|
||||||
res_data['statements'].replace(
|
|
||||||
res_data['schema'], diff_schema)
|
|
||||||
res_data['schema'] = diff_schema
|
|
||||||
|
|
||||||
@check_precondition
|
@check_precondition
|
||||||
def dependents(self, gid, sid, did, scid, tid, rid):
|
def dependents(self, gid, sid, did, scid, tid, rid):
|
||||||
"""
|
"""
|
||||||
@@ -675,7 +649,6 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
tgt_params = kwargs.get('target_params')
|
tgt_params = kwargs.get('target_params')
|
||||||
source = kwargs.get('source')
|
source = kwargs.get('source')
|
||||||
target = kwargs.get('target')
|
target = kwargs.get('target')
|
||||||
target_schema = kwargs.get('target_schema')
|
|
||||||
comp_status = kwargs.get('comp_status')
|
comp_status = kwargs.get('comp_status')
|
||||||
|
|
||||||
diff = ''
|
diff = ''
|
||||||
@@ -685,8 +658,7 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
did=src_params['did'],
|
did=src_params['did'],
|
||||||
scid=src_params['scid'],
|
scid=src_params['scid'],
|
||||||
tid=src_params['tid'],
|
tid=src_params['tid'],
|
||||||
oid=source['oid'],
|
oid=source['oid'])
|
||||||
diff_schema=target_schema)
|
|
||||||
elif comp_status == 'target_only':
|
elif comp_status == 'target_only':
|
||||||
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
|
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
|
||||||
sid=tgt_params['sid'],
|
sid=tgt_params['sid'],
|
||||||
@@ -708,8 +680,6 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
scid=tgt_params['scid'],
|
scid=tgt_params['scid'],
|
||||||
tid=tgt_params['tid'],
|
tid=tgt_params['tid'],
|
||||||
oid=target['oid'],
|
oid=target['oid'],
|
||||||
source_schema=source['schema'],
|
|
||||||
diff_schema=target_schema,
|
|
||||||
data=diff_dict)
|
data=diff_dict)
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
|
|||||||
@@ -51,12 +51,15 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
'did': kwargs.get('target_did'),
|
'did': kwargs.get('target_did'),
|
||||||
'scid': kwargs.get('target_scid')}
|
'scid': kwargs.get('target_scid')}
|
||||||
|
|
||||||
|
group_name = kwargs.get('group_name')
|
||||||
ignore_whitespaces = kwargs.get('ignore_whitespaces')
|
ignore_whitespaces = kwargs.get('ignore_whitespaces')
|
||||||
status, target_schema = self.get_schema(**target_params)
|
source_tables = {}
|
||||||
if not status:
|
target_tables = {}
|
||||||
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)
|
source_tables = self.fetch_tables(**source_params)
|
||||||
|
|
||||||
|
if 'scid' in target_params and target_params['scid'] is not None:
|
||||||
target_tables = self.fetch_tables(**target_params)
|
target_tables = self.fetch_tables(**target_params)
|
||||||
|
|
||||||
# If both the dict have no items then return None.
|
# If both the dict have no items then return None.
|
||||||
@@ -67,11 +70,11 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
return compare_dictionaries(view_object=self,
|
return compare_dictionaries(view_object=self,
|
||||||
source_params=source_params,
|
source_params=source_params,
|
||||||
target_params=target_params,
|
target_params=target_params,
|
||||||
target_schema=target_schema,
|
|
||||||
source_dict=source_tables,
|
source_dict=source_tables,
|
||||||
target_dict=target_tables,
|
target_dict=target_tables,
|
||||||
node=self.node_type,
|
node=self.node_type,
|
||||||
node_label=self.blueprint.collection_label,
|
node_label=self.blueprint.collection_label,
|
||||||
|
group_name=group_name,
|
||||||
ignore_whitespaces=ignore_whitespaces,
|
ignore_whitespaces=ignore_whitespaces,
|
||||||
ignore_keys=self.keys_to_ignore)
|
ignore_keys=self.keys_to_ignore)
|
||||||
|
|
||||||
@@ -239,7 +242,6 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
"""
|
"""
|
||||||
source_params = kwargs.get('source_params')
|
source_params = kwargs.get('source_params')
|
||||||
target_params = kwargs.get('target_params')
|
target_params = kwargs.get('target_params')
|
||||||
target_schema = kwargs.get('target_schema')
|
|
||||||
source = kwargs.get('source')
|
source = kwargs.get('source')
|
||||||
target = kwargs.get('target')
|
target = kwargs.get('target')
|
||||||
diff_dict = kwargs.get('diff_dict')
|
diff_dict = kwargs.get('diff_dict')
|
||||||
@@ -297,7 +299,6 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
target_params=target_params,
|
target_params=target_params,
|
||||||
source=dict1[item],
|
source=dict1[item],
|
||||||
target=None,
|
target=None,
|
||||||
target_schema=target_schema,
|
|
||||||
comp_status='source_only'
|
comp_status='source_only'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -311,7 +312,6 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
target_params=target_params,
|
target_params=target_params,
|
||||||
source=None,
|
source=None,
|
||||||
target=dict2[item],
|
target=dict2[item],
|
||||||
target_schema=target_schema,
|
|
||||||
comp_status='target_only'
|
comp_status='target_only'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -329,7 +329,6 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare):
|
|||||||
target_params=target_params,
|
target_params=target_params,
|
||||||
source=dict1[key],
|
source=dict1[key],
|
||||||
target=dict2[key],
|
target=dict2[key],
|
||||||
target_schema=target_schema,
|
|
||||||
comp_status='different',
|
comp_status='different',
|
||||||
parent_source_data=source,
|
parent_source_data=source,
|
||||||
parent_target_data=target
|
parent_target_data=target
|
||||||
|
|||||||
@@ -805,7 +805,6 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
tid = kwargs.get('tid')
|
tid = kwargs.get('tid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
@@ -825,8 +824,6 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
only_sql=True)
|
only_sql=True)
|
||||||
else:
|
else:
|
||||||
schema = self.schema
|
schema = self.schema
|
||||||
if diff_schema:
|
|
||||||
schema = diff_schema
|
|
||||||
SQL = trigger_utils.get_reverse_engineered_sql(
|
SQL = trigger_utils.get_reverse_engineered_sql(
|
||||||
self.conn, schema=schema, table=self.table, tid=tid,
|
self.conn, schema=schema, table=self.table, tid=tid,
|
||||||
trid=oid, datlastsysoid=self.datlastsysoid,
|
trid=oid, datlastsysoid=self.datlastsysoid,
|
||||||
@@ -997,7 +994,6 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
tgt_params = kwargs.get('target_params')
|
tgt_params = kwargs.get('target_params')
|
||||||
source = kwargs.get('source')
|
source = kwargs.get('source')
|
||||||
target = kwargs.get('target')
|
target = kwargs.get('target')
|
||||||
target_schema = kwargs.get('target_schema')
|
|
||||||
comp_status = kwargs.get('comp_status')
|
comp_status = kwargs.get('comp_status')
|
||||||
|
|
||||||
diff = ''
|
diff = ''
|
||||||
@@ -1007,8 +1003,7 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare):
|
|||||||
did=src_params['did'],
|
did=src_params['did'],
|
||||||
scid=src_params['scid'],
|
scid=src_params['scid'],
|
||||||
tid=src_params['tid'],
|
tid=src_params['tid'],
|
||||||
oid=source['oid'],
|
oid=source['oid'])
|
||||||
diff_schema=target_schema)
|
|
||||||
elif comp_status == 'target_only':
|
elif comp_status == 'target_only':
|
||||||
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
|
diff = self.get_sql_from_diff(gid=tgt_params['gid'],
|
||||||
sid=tgt_params['sid'],
|
sid=tgt_params['sid'],
|
||||||
|
|||||||
@@ -145,6 +145,13 @@ class BaseTableView(PGChildNodeView, BasePartitionTable):
|
|||||||
# Supported ACL for columns
|
# Supported ACL for columns
|
||||||
self.column_acl = ['a', 'r', 'w', 'x']
|
self.column_acl = ['a', 'r', 'w', 'x']
|
||||||
|
|
||||||
|
# Submodule list for schema diff
|
||||||
|
self.tables_sub_modules = ['index', 'rule', 'trigger']
|
||||||
|
if server_type == 'ppas' and ver >= 120000:
|
||||||
|
self.tables_sub_modules.append('compound_trigger')
|
||||||
|
if ver >= 90500:
|
||||||
|
self.tables_sub_modules.append('row_security_policy')
|
||||||
|
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
return wrap
|
return wrap
|
||||||
|
|||||||
@@ -1363,10 +1363,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
|||||||
did: Database ID
|
did: Database ID
|
||||||
scid: Schema ID
|
scid: Schema ID
|
||||||
tid: Type ID
|
tid: Type ID
|
||||||
diff_schema: Target Schema for schema diff
|
|
||||||
json_resp: True then return json response
|
json_resp: True then return json response
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
SQL = render_template(
|
SQL = render_template(
|
||||||
@@ -1386,9 +1384,6 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
|||||||
# Making copy of output for future use
|
# Making copy of output for future use
|
||||||
data = dict(res['rows'][0])
|
data = dict(res['rows'][0])
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
|
|
||||||
SQL = render_template("/".join([self.template_path, self._ACL_SQL]),
|
SQL = render_template("/".join([self.template_path, self._ACL_SQL]),
|
||||||
scid=scid, tid=tid)
|
scid=scid, tid=tid)
|
||||||
status, acl = self.conn.execute_dict(SQL)
|
status, acl = self.conn.execute_dict(SQL)
|
||||||
@@ -1518,21 +1513,15 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name = self.get_sql(gid=gid, sid=sid, scid=scid,
|
sql, name = self.get_sql(gid=gid, sid=sid, scid=scid,
|
||||||
data=data, tid=oid)
|
data=data, tid=oid)
|
||||||
else:
|
else:
|
||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, tid=oid, only_sql=True)
|
scid=scid, tid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, tid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
|
|||||||
@@ -1305,9 +1305,7 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
|
|||||||
"""
|
"""
|
||||||
This function will generate sql to render into the sql panel
|
This function will generate sql to render into the sql panel
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
display_comments = True
|
display_comments = True
|
||||||
|
|
||||||
if not json_resp:
|
if not json_resp:
|
||||||
@@ -1329,11 +1327,6 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
|
|||||||
)
|
)
|
||||||
|
|
||||||
result = res['rows'][0]
|
result = res['rows'][0]
|
||||||
if diff_schema:
|
|
||||||
result['definition'] = result['definition'].replace(
|
|
||||||
result['schema'],
|
|
||||||
diff_schema)
|
|
||||||
result['schema'] = diff_schema
|
|
||||||
|
|
||||||
# sending result to formtter
|
# sending result to formtter
|
||||||
frmtd_reslt = self.formatter(result)
|
frmtd_reslt = self.formatter(result)
|
||||||
@@ -1631,12 +1624,9 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
|
|||||||
scid = kwargs.get('scid')
|
scid = kwargs.get('scid')
|
||||||
oid = kwargs.get('oid')
|
oid = kwargs.get('oid')
|
||||||
data = kwargs.get('data', None)
|
data = kwargs.get('data', None)
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
drop_sql = kwargs.get('drop_sql', False)
|
drop_sql = kwargs.get('drop_sql', False)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if diff_schema:
|
|
||||||
data['schema'] = diff_schema
|
|
||||||
sql, name_or_error = self.getSQL(gid, sid, did, data, oid)
|
sql, name_or_error = self.getSQL(gid, sid, did, data, oid)
|
||||||
if sql.find('DROP VIEW') != -1:
|
if sql.find('DROP VIEW') != -1:
|
||||||
sql = gettext("""
|
sql = gettext("""
|
||||||
@@ -1649,9 +1639,6 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
|
|||||||
if drop_sql:
|
if drop_sql:
|
||||||
sql = self.delete(gid=gid, sid=sid, did=did,
|
sql = self.delete(gid=gid, sid=sid, did=did,
|
||||||
scid=scid, vid=oid, only_sql=True)
|
scid=scid, vid=oid, only_sql=True)
|
||||||
elif diff_schema:
|
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, vid=oid,
|
|
||||||
diff_schema=diff_schema, json_resp=False)
|
|
||||||
else:
|
else:
|
||||||
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, vid=oid,
|
sql = self.sql(gid=gid, sid=sid, did=did, scid=scid, vid=oid,
|
||||||
json_resp=False)
|
json_resp=False)
|
||||||
@@ -1885,7 +1872,6 @@ class MViewNode(ViewNode, VacuumSettings):
|
|||||||
"""
|
"""
|
||||||
This function will generate sql to render into the sql panel
|
This function will generate sql to render into the sql panel
|
||||||
"""
|
"""
|
||||||
diff_schema = kwargs.get('diff_schema', None)
|
|
||||||
json_resp = kwargs.get('json_resp', True)
|
json_resp = kwargs.get('json_resp', True)
|
||||||
|
|
||||||
display_comments = True
|
display_comments = True
|
||||||
@@ -1899,12 +1885,6 @@ class MViewNode(ViewNode, VacuumSettings):
|
|||||||
if not status:
|
if not status:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
if diff_schema:
|
|
||||||
result['definition'] = result['definition'].replace(
|
|
||||||
result['schema'],
|
|
||||||
diff_schema)
|
|
||||||
result['schema'] = diff_schema
|
|
||||||
|
|
||||||
# merge vacuum lists into one
|
# merge vacuum lists into one
|
||||||
vacuum_table = [item for item in result['vacuum_table']
|
vacuum_table = [item for item in result['vacuum_table']
|
||||||
if
|
if
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT DISTINCT dep.deptype, dep.refclassid, cl.relkind, ad.adbin, ad.adsrc,
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
||||||
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
||||||
@@ -70,4 +70,18 @@ refclassid IN ( SELECT oid FROM pg_class WHERE relname IN
|
|||||||
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
||||||
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
||||||
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension'))
|
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension'))
|
||||||
ORDER BY refclassid, cl.relkind
|
UNION
|
||||||
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
|
ELSE '' END AS type,
|
||||||
|
NULL AS ownertable,
|
||||||
|
CASE WHEN cl.relname IS NOT NULL OR att.attname IS NOT NULL THEN cl.relname || COALESCE('.' || att.attname, '')
|
||||||
|
ELSE cl.relname END AS refname,
|
||||||
|
nsc.nspname AS nspname, '0' AS is_inherits, '0' AS is_inherited
|
||||||
|
FROM pg_depend dep
|
||||||
|
LEFT JOIN pg_class cl ON dep.refobjid=cl.oid
|
||||||
|
LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum
|
||||||
|
LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid
|
||||||
|
LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum
|
||||||
|
WHERE dep.objid IN (SELECT oid FROM pg_rewrite WHERE ev_class={{object_id}}) AND cl.relkind not in ('v', 'm')
|
||||||
|
ORDER BY refclassid, relkind
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT DISTINCT dep.deptype, dep.refclassid, cl.relkind, ad.adbin, ad.adsrc,
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
||||||
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
||||||
@@ -72,4 +72,18 @@ refclassid IN ( SELECT oid FROM pg_class WHERE relname IN
|
|||||||
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
||||||
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
||||||
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension', 'pg_policy'))
|
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension', 'pg_policy'))
|
||||||
ORDER BY refclassid, cl.relkind
|
UNION
|
||||||
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
|
ELSE '' END AS type,
|
||||||
|
NULL AS ownertable,
|
||||||
|
CASE WHEN cl.relname IS NOT NULL OR att.attname IS NOT NULL THEN cl.relname || COALESCE('.' || att.attname, '')
|
||||||
|
ELSE cl.relname END AS refname,
|
||||||
|
nsc.nspname AS nspname, '0' AS is_inherits, '0' AS is_inherited
|
||||||
|
FROM pg_depend dep
|
||||||
|
LEFT JOIN pg_class cl ON dep.refobjid=cl.oid
|
||||||
|
LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum
|
||||||
|
LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid
|
||||||
|
LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum
|
||||||
|
WHERE dep.objid IN (SELECT oid FROM pg_rewrite WHERE ev_class={{object_id}}) AND cl.relkind not in ('v', 'm')
|
||||||
|
ORDER BY refclassid, relkind
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT DISTINCT dep.deptype, dep.refclassid, cl.relkind, ad.adbin, pg_get_expr(ad.adbin, ad.adrelid) as adsrc,
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, pg_get_expr(ad.adbin, ad.adrelid) as adsrc,
|
||||||
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
||||||
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
||||||
@@ -72,4 +72,18 @@ refclassid IN ( SELECT oid FROM pg_class WHERE relname IN
|
|||||||
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
||||||
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
||||||
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension', 'pg_policy'))
|
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension', 'pg_policy'))
|
||||||
ORDER BY refclassid, cl.relkind
|
UNION
|
||||||
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, pg_get_expr(ad.adbin, ad.adrelid) as adsrc,
|
||||||
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
|
ELSE '' END AS type,
|
||||||
|
NULL AS ownertable,
|
||||||
|
CASE WHEN cl.relname IS NOT NULL OR att.attname IS NOT NULL THEN cl.relname || COALESCE('.' || att.attname, '')
|
||||||
|
ELSE cl.relname END AS refname,
|
||||||
|
nsc.nspname AS nspname, '0' AS is_inherits, '0' AS is_inherited
|
||||||
|
FROM pg_depend dep
|
||||||
|
LEFT JOIN pg_class cl ON dep.refobjid=cl.oid
|
||||||
|
LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum
|
||||||
|
LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid
|
||||||
|
LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum
|
||||||
|
WHERE dep.objid IN (SELECT oid FROM pg_rewrite WHERE ev_class={{object_id}}) AND cl.relkind not in ('v', 'm')
|
||||||
|
ORDER BY refclassid, relkind
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT DISTINCT dep.deptype, dep.refclassid, cl.relkind, ad.adbin, ad.adsrc,
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
||||||
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
||||||
@@ -70,4 +70,18 @@ refclassid IN ( SELECT oid FROM pg_class WHERE relname IN
|
|||||||
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
||||||
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
||||||
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension'))
|
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension'))
|
||||||
ORDER BY refclassid, cl.relkind
|
UNION
|
||||||
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
|
ELSE '' END AS type,
|
||||||
|
NULL AS ownertable,
|
||||||
|
CASE WHEN cl.relname IS NOT NULL OR att.attname IS NOT NULL THEN cl.relname || COALESCE('.' || att.attname, '')
|
||||||
|
ELSE cl.relname END AS refname,
|
||||||
|
nsc.nspname AS nspname, '0' AS is_inherits, '0' AS is_inherited
|
||||||
|
FROM pg_depend dep
|
||||||
|
LEFT JOIN pg_class cl ON dep.refobjid=cl.oid
|
||||||
|
LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum
|
||||||
|
LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid
|
||||||
|
LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum
|
||||||
|
WHERE dep.objid IN (SELECT oid FROM pg_rewrite WHERE ev_class={{object_id}}) AND cl.relkind not in ('v', 'm')
|
||||||
|
ORDER BY refclassid, relkind
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT DISTINCT dep.deptype, dep.refclassid, cl.relkind, ad.adbin, ad.adsrc,
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
||||||
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
||||||
@@ -72,4 +72,18 @@ refclassid IN ( SELECT oid FROM pg_class WHERE relname IN
|
|||||||
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_rewrite', 'pg_namespace',
|
||||||
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
||||||
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension', 'pg_policy'))
|
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension', 'pg_policy'))
|
||||||
ORDER BY refclassid, cl.relkind
|
UNION
|
||||||
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
|
ELSE '' END AS type,
|
||||||
|
NULL AS ownertable,
|
||||||
|
CASE WHEN cl.relname IS NOT NULL OR att.attname IS NOT NULL THEN cl.relname || COALESCE('.' || att.attname, '')
|
||||||
|
ELSE cl.relname END AS refname,
|
||||||
|
nsc.nspname AS nspname, '0' AS is_inherits, '0' AS is_inherited
|
||||||
|
FROM pg_depend dep
|
||||||
|
LEFT JOIN pg_class cl ON dep.refobjid=cl.oid
|
||||||
|
LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum
|
||||||
|
LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid
|
||||||
|
LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum
|
||||||
|
WHERE dep.objid IN (SELECT oid FROM pg_rewrite WHERE ev_class={{object_id}}) AND cl.relkind not in ('v', 'm')
|
||||||
|
ORDER BY refclassid, relkind
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT DISTINCT dep.deptype, dep.refclassid, cl.relkind, ad.adbin, ad.adsrc,
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
||||||
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
||||||
@@ -76,4 +76,18 @@ refclassid IN ( SELECT oid FROM pg_class WHERE relname IN
|
|||||||
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
||||||
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension',
|
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension',
|
||||||
'pg_synonym', 'pg_policy'))
|
'pg_synonym', 'pg_policy'))
|
||||||
ORDER BY refclassid, cl.relkind
|
UNION
|
||||||
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
|
ELSE '' END AS type,
|
||||||
|
NULL AS ownertable,
|
||||||
|
CASE WHEN cl.relname IS NOT NULL OR att.attname IS NOT NULL THEN cl.relname || COALESCE('.' || att.attname, '')
|
||||||
|
ELSE cl.relname END AS refname,
|
||||||
|
nsc.nspname AS nspname, '0' AS is_inherits, '0' AS is_inherited
|
||||||
|
FROM pg_depend dep
|
||||||
|
LEFT JOIN pg_class cl ON dep.refobjid=cl.oid
|
||||||
|
LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum
|
||||||
|
LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid
|
||||||
|
LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum
|
||||||
|
WHERE dep.objid IN (SELECT oid FROM pg_rewrite WHERE ev_class={{object_id}}) AND cl.relkind not in ('v', 'm')
|
||||||
|
ORDER BY refclassid, relkind
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT DISTINCT dep.deptype, dep.refclassid, cl.relkind, ad.adbin, pg_get_expr(ad.adbin, ad.adrelid) as adsrc,
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, pg_get_expr(ad.adbin, ad.adrelid) as adsrc,
|
||||||
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
WHEN tg.oid IS NOT NULL THEN CASE WHEN tg.tgpackageoid != 0 THEN 'Tc'::text ELSE 'Tr'::text END
|
WHEN tg.oid IS NOT NULL THEN CASE WHEN tg.tgpackageoid != 0 THEN 'Tc'::text ELSE 'Tr'::text END
|
||||||
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
||||||
@@ -76,4 +76,18 @@ refclassid IN ( SELECT oid FROM pg_class WHERE relname IN
|
|||||||
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
||||||
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension',
|
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension',
|
||||||
'pg_synonym', 'pg_policy'))
|
'pg_synonym', 'pg_policy'))
|
||||||
ORDER BY refclassid, cl.relkind
|
UNION
|
||||||
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, pg_get_expr(ad.adbin, ad.adrelid) as adsrc,
|
||||||
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
|
ELSE '' END AS type,
|
||||||
|
NULL AS ownertable,
|
||||||
|
CASE WHEN cl.relname IS NOT NULL OR att.attname IS NOT NULL THEN cl.relname || COALESCE('.' || att.attname, '')
|
||||||
|
ELSE cl.relname END AS refname,
|
||||||
|
nsc.nspname AS nspname, '0' AS is_inherits, '0' AS is_inherited
|
||||||
|
FROM pg_depend dep
|
||||||
|
LEFT JOIN pg_class cl ON dep.refobjid=cl.oid
|
||||||
|
LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum
|
||||||
|
LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid
|
||||||
|
LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum
|
||||||
|
WHERE dep.objid IN (SELECT oid FROM pg_rewrite WHERE ev_class={{object_id}}) AND cl.relkind not in ('v', 'm')
|
||||||
|
ORDER BY refclassid, relkind
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT DISTINCT dep.deptype, dep.refclassid, cl.relkind, ad.adbin, ad.adsrc,
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
||||||
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
||||||
@@ -74,4 +74,18 @@ refclassid IN ( SELECT oid FROM pg_class WHERE relname IN
|
|||||||
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
||||||
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension',
|
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension',
|
||||||
'pg_synonym'))
|
'pg_synonym'))
|
||||||
ORDER BY refclassid, cl.relkind
|
UNION
|
||||||
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
|
ELSE '' END AS type,
|
||||||
|
NULL AS ownertable,
|
||||||
|
CASE WHEN cl.relname IS NOT NULL OR att.attname IS NOT NULL THEN cl.relname || COALESCE('.' || att.attname, '')
|
||||||
|
ELSE cl.relname END AS refname,
|
||||||
|
nsc.nspname AS nspname, '0' AS is_inherits, '0' AS is_inherited
|
||||||
|
FROM pg_depend dep
|
||||||
|
LEFT JOIN pg_class cl ON dep.refobjid=cl.oid
|
||||||
|
LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum
|
||||||
|
LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid
|
||||||
|
LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum
|
||||||
|
WHERE dep.objid IN (SELECT oid FROM pg_rewrite WHERE ev_class={{object_id}}) AND cl.relkind not in ('v', 'm')
|
||||||
|
ORDER BY refclassid, relkind
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT DISTINCT dep.deptype, dep.refclassid, cl.relkind, ad.adbin, ad.adsrc,
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
WHEN tg.oid IS NOT NULL THEN 'Tr'::text
|
||||||
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
WHEN ty.oid IS NOT NULL THEN CASE WHEN ty.typtype = 'd' THEN 'd'::text ELSE 'Ty'::text END
|
||||||
@@ -76,4 +76,18 @@ refclassid IN ( SELECT oid FROM pg_class WHERE relname IN
|
|||||||
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger', 'pg_foreign_server', 'pg_foreign_data_wrapper',
|
||||||
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension',
|
'pg_collation', 'pg_ts_config', 'pg_ts_dict', 'pg_ts_parser', 'pg_ts_template', 'pg_extension',
|
||||||
'pg_synonym', 'pg_policy'))
|
'pg_synonym', 'pg_policy'))
|
||||||
ORDER BY refclassid, cl.relkind
|
UNION
|
||||||
|
SELECT DISTINCT dep.deptype, dep.refclassid, dep.refobjid, cl.relkind, ad.adbin, ad.adsrc,
|
||||||
|
CASE WHEN cl.relkind IS NOT NULL THEN CASE WHEN cl.relkind = 'r' THEN cl.relkind || COALESCE(dep.refobjsubid::text, '') ELSE cl.relkind END
|
||||||
|
ELSE '' END AS type,
|
||||||
|
NULL AS ownertable,
|
||||||
|
CASE WHEN cl.relname IS NOT NULL OR att.attname IS NOT NULL THEN cl.relname || COALESCE('.' || att.attname, '')
|
||||||
|
ELSE cl.relname END AS refname,
|
||||||
|
nsc.nspname AS nspname, '0' AS is_inherits, '0' AS is_inherited
|
||||||
|
FROM pg_depend dep
|
||||||
|
LEFT JOIN pg_class cl ON dep.refobjid=cl.oid
|
||||||
|
LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum
|
||||||
|
LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid
|
||||||
|
LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum
|
||||||
|
WHERE dep.objid IN (SELECT oid FROM pg_rewrite WHERE ev_class={{object_id}}) AND cl.relkind not in ('v', 'm')
|
||||||
|
ORDER BY refclassid, relkind
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ class TestDependenciesSql(SQLTemplateTestBase):
|
|||||||
"dependencies.sql")
|
"dependencies.sql")
|
||||||
template = file_as_template(template_file)
|
template = file_as_template(template_file)
|
||||||
sql = template.render(
|
sql = template.render(
|
||||||
where_clause="WHERE dep.objid=%s::oid" % self.table_id)
|
where_clause="WHERE dep.objid=%s::oid" % self.table_id,
|
||||||
|
object_id=self.table_id)
|
||||||
|
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
|
|||||||
@@ -451,7 +451,7 @@ class PGChildNodeView(NodeView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_dependencies(self, conn, object_id, where=None,
|
def get_dependencies(self, conn, object_id, where=None,
|
||||||
show_system_objects=None):
|
show_system_objects=None, is_schema_diff=False):
|
||||||
"""
|
"""
|
||||||
This function is used to fetch the dependencies for the selected node.
|
This function is used to fetch the dependencies for the selected node.
|
||||||
|
|
||||||
@@ -459,6 +459,8 @@ class PGChildNodeView(NodeView):
|
|||||||
conn: Connection object
|
conn: Connection object
|
||||||
object_id: Object Id of the selected node.
|
object_id: Object Id of the selected node.
|
||||||
where: where clause for the sql query (optional)
|
where: where clause for the sql query (optional)
|
||||||
|
show_system_objects: System object status
|
||||||
|
is_schema_diff: True when function gets called from schema diff.
|
||||||
|
|
||||||
Returns: Dictionary of dependencies for the selected node.
|
Returns: Dictionary of dependencies for the selected node.
|
||||||
"""
|
"""
|
||||||
@@ -473,10 +475,11 @@ class PGChildNodeView(NodeView):
|
|||||||
where_clause = where
|
where_clause = where
|
||||||
|
|
||||||
query = render_template("/".join([sql_path, 'dependencies.sql']),
|
query = render_template("/".join([sql_path, 'dependencies.sql']),
|
||||||
where_clause=where_clause)
|
where_clause=where_clause,
|
||||||
|
object_id=object_id)
|
||||||
# fetch the dependency for the selected object
|
# fetch the dependency for the selected object
|
||||||
dependencies = self.__fetch_dependency(conn, query,
|
dependencies = self.__fetch_dependency(
|
||||||
show_system_objects)
|
conn, query, show_system_objects, is_schema_diff)
|
||||||
|
|
||||||
# fetch role dependencies
|
# fetch role dependencies
|
||||||
if where_clause.find('subid') < 0:
|
if where_clause.find('subid') < 0:
|
||||||
@@ -534,13 +537,16 @@ class PGChildNodeView(NodeView):
|
|||||||
|
|
||||||
return dependents
|
return dependents
|
||||||
|
|
||||||
def __fetch_dependency(self, conn, query, show_system_objects=None):
|
def __fetch_dependency(self, conn, query, show_system_objects=None,
|
||||||
|
is_schema_diff=False):
|
||||||
"""
|
"""
|
||||||
This function is used to fetch the dependency for the selected node.
|
This function is used to fetch the dependency for the selected node.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
conn: Connection object
|
conn: Connection object
|
||||||
query: sql query to fetch dependencies/dependents
|
query: sql query to fetch dependencies/dependents
|
||||||
|
show_system_objects: System object status
|
||||||
|
is_schema_diff: True when function gets called from schema diff.
|
||||||
|
|
||||||
Returns: Dictionary of dependency for the selected node.
|
Returns: Dictionary of dependency for the selected node.
|
||||||
"""
|
"""
|
||||||
@@ -597,6 +603,9 @@ class PGChildNodeView(NodeView):
|
|||||||
type_str = row['type']
|
type_str = row['type']
|
||||||
dep_str = row['deptype']
|
dep_str = row['deptype']
|
||||||
nsp_name = row['nspname']
|
nsp_name = row['nspname']
|
||||||
|
object_id = None
|
||||||
|
if 'refobjid' in row:
|
||||||
|
object_id = row['refobjid']
|
||||||
|
|
||||||
ref_name = ''
|
ref_name = ''
|
||||||
if nsp_name is not None:
|
if nsp_name is not None:
|
||||||
@@ -658,12 +667,24 @@ class PGChildNodeView(NodeView):
|
|||||||
if _ref_name is not None:
|
if _ref_name is not None:
|
||||||
ref_name += _ref_name
|
ref_name += _ref_name
|
||||||
|
|
||||||
|
# If schema diff is set to True then we don't need to calculate
|
||||||
|
# field and also no need to add icon and field in the list.
|
||||||
|
if is_schema_diff and type_name != 'schema':
|
||||||
|
dependency.append(
|
||||||
|
{
|
||||||
|
'type': type_name,
|
||||||
|
'name': ref_name,
|
||||||
|
'oid': object_id
|
||||||
|
}
|
||||||
|
)
|
||||||
|
elif not is_schema_diff:
|
||||||
dep_type = ''
|
dep_type = ''
|
||||||
if show_system_objects is None:
|
if show_system_objects is None:
|
||||||
show_system_objects = self.blueprint.show_system_objects
|
show_system_objects = self.blueprint.show_system_objects
|
||||||
if dep_str[0] in dep_types:
|
if dep_str[0] in dep_types:
|
||||||
# if dep_type is present in the dep_types dictionary, but it's
|
# if dep_type is present in the dep_types dictionary,
|
||||||
# value is None then it requires special handling.
|
# but it's value is None then it requires special
|
||||||
|
# handling.
|
||||||
if dep_types[dep_str[0]] is None:
|
if dep_types[dep_str[0]] is None:
|
||||||
if dep_str[0] == 'i':
|
if dep_str[0] == 'i':
|
||||||
if show_system_objects:
|
if show_system_objects:
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
import simplejson as json
|
import simplejson as json
|
||||||
import pickle
|
import pickle
|
||||||
import random
|
import random
|
||||||
|
import copy
|
||||||
|
|
||||||
from flask import Response, session, url_for, request
|
from flask import Response, session, url_for, request
|
||||||
from flask import render_template, current_app as app
|
from flask import render_template, current_app as app
|
||||||
@@ -61,7 +62,6 @@ class SchemaDiffModule(PgAdminModule):
|
|||||||
'schema_diff.panel',
|
'schema_diff.panel',
|
||||||
'schema_diff.servers',
|
'schema_diff.servers',
|
||||||
'schema_diff.databases',
|
'schema_diff.databases',
|
||||||
'schema_diff.schemas',
|
|
||||||
'schema_diff.compare',
|
'schema_diff.compare',
|
||||||
'schema_diff.poll',
|
'schema_diff.poll',
|
||||||
'schema_diff.ddl_compare',
|
'schema_diff.ddl_compare',
|
||||||
@@ -397,46 +397,14 @@ def databases(sid):
|
|||||||
return make_json_response(data=res)
|
return make_json_response(data=res)
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route(
|
|
||||||
'/schemas/<int:sid>/<int:did>',
|
|
||||||
methods=["GET"],
|
|
||||||
endpoint="schemas"
|
|
||||||
)
|
|
||||||
@login_required
|
|
||||||
def schemas(sid, did):
|
|
||||||
"""
|
|
||||||
This function will return the list of schemas for the specified
|
|
||||||
server id and database id.
|
|
||||||
"""
|
|
||||||
res = []
|
|
||||||
try:
|
|
||||||
view = SchemaDiffRegistry.get_node_view('schema')
|
|
||||||
server = Server.query.filter_by(id=sid).first()
|
|
||||||
response = view.nodes(gid=server.servergroup_id, sid=sid, did=did)
|
|
||||||
if response.status_code == 200:
|
|
||||||
schemas = json.loads(response.data)['data']
|
|
||||||
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(
|
@blueprint.route(
|
||||||
'/compare/<int:trans_id>/<int:source_sid>/<int:source_did>/'
|
'/compare/<int:trans_id>/<int:source_sid>/<int:source_did>/'
|
||||||
'<int:source_scid>/<int:target_sid>/<int:target_did>/<int:target_scid>',
|
'<int:target_sid>/<int:target_did>',
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
endpoint="compare"
|
endpoint="compare"
|
||||||
)
|
)
|
||||||
@login_required
|
@login_required
|
||||||
def compare(trans_id, source_sid, source_did, source_scid,
|
def compare(trans_id, source_sid, source_did, target_sid, target_did):
|
||||||
target_sid, target_did, target_scid):
|
|
||||||
"""
|
"""
|
||||||
This function will compare the two schemas.
|
This function will compare the two schemas.
|
||||||
"""
|
"""
|
||||||
@@ -463,33 +431,88 @@ def compare(trans_id, source_sid, source_did, source_scid,
|
|||||||
pref = Preferences.module('schema_diff')
|
pref = Preferences.module('schema_diff')
|
||||||
ignore_whitespaces = pref.preference('ignore_whitespaces').get()
|
ignore_whitespaces = pref.preference('ignore_whitespaces').get()
|
||||||
|
|
||||||
all_registered_nodes = SchemaDiffRegistry.get_registered_nodes()
|
# Fetch all the schemas of source and target database
|
||||||
node_percent = round(100 / len(all_registered_nodes))
|
# Compare them and get the status.
|
||||||
|
schema_result = fetch_compare_schemas(source_sid, source_did,
|
||||||
|
target_sid, target_did)
|
||||||
|
|
||||||
|
total_schema = len(schema_result['source_only']) + len(
|
||||||
|
schema_result['target_only']) + len(
|
||||||
|
schema_result['in_both_database'])
|
||||||
|
|
||||||
|
node_percent = round(100 / (total_schema * len(
|
||||||
|
SchemaDiffRegistry.get_registered_nodes())))
|
||||||
total_percent = 0
|
total_percent = 0
|
||||||
|
|
||||||
for node_name, node_view in all_registered_nodes.items():
|
# Compare Database objects
|
||||||
view = SchemaDiffRegistry.get_node_view(node_name)
|
comparison_schema_result, total_percent = \
|
||||||
if hasattr(view, 'compare'):
|
compare_database_objects(
|
||||||
msg = gettext('Comparing {0}').\
|
trans_id=trans_id, session_obj=session_obj,
|
||||||
format(gettext(view.blueprint.collection_label))
|
source_sid=source_sid, source_did=source_did,
|
||||||
diff_model_obj.set_comparison_info(msg, total_percent)
|
target_sid=target_sid, target_did=target_did,
|
||||||
# Update the message and total percentage in session object
|
diff_model_obj=diff_model_obj, total_percent=total_percent,
|
||||||
update_session_diff_transaction(trans_id, session_obj,
|
node_percent=node_percent,
|
||||||
diff_model_obj)
|
ignore_whitespaces=ignore_whitespaces)
|
||||||
|
comparison_result = \
|
||||||
|
comparison_result + comparison_schema_result
|
||||||
|
|
||||||
res = view.compare(source_sid=source_sid,
|
# Compare Schema objects
|
||||||
source_did=source_did,
|
if 'source_only' in schema_result and \
|
||||||
source_scid=source_scid,
|
len(schema_result['source_only']) > 0:
|
||||||
target_sid=target_sid,
|
for item in schema_result['source_only']:
|
||||||
target_did=target_did,
|
comparison_schema_result, total_percent = \
|
||||||
target_scid=target_scid,
|
compare_schema_objects(
|
||||||
|
trans_id=trans_id, session_obj=session_obj,
|
||||||
|
source_sid=source_sid, source_did=source_did,
|
||||||
|
source_scid=item['scid'], target_sid=target_sid,
|
||||||
|
target_did=target_did, target_scid=None,
|
||||||
|
schema_name=item['schema_name'],
|
||||||
|
diff_model_obj=diff_model_obj,
|
||||||
|
total_percent=total_percent,
|
||||||
|
node_percent=node_percent,
|
||||||
ignore_whitespaces=ignore_whitespaces)
|
ignore_whitespaces=ignore_whitespaces)
|
||||||
|
|
||||||
if res is not None:
|
comparison_result = \
|
||||||
comparison_result = comparison_result + res
|
comparison_result + comparison_schema_result
|
||||||
total_percent = total_percent + node_percent
|
|
||||||
|
|
||||||
msg = gettext("Successfully compare the specified schemas.")
|
if 'target_only' in schema_result and \
|
||||||
|
len(schema_result['target_only']) > 0:
|
||||||
|
for item in schema_result['target_only']:
|
||||||
|
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=None, target_sid=target_sid,
|
||||||
|
target_did=target_did, target_scid=item['scid'],
|
||||||
|
schema_name=item['schema_name'],
|
||||||
|
diff_model_obj=diff_model_obj,
|
||||||
|
total_percent=total_percent,
|
||||||
|
node_percent=node_percent,
|
||||||
|
ignore_whitespaces=ignore_whitespaces)
|
||||||
|
|
||||||
|
comparison_result = \
|
||||||
|
comparison_result + comparison_schema_result
|
||||||
|
|
||||||
|
# Compare the two schema present in both the databases
|
||||||
|
if 'in_both_database' in schema_result and \
|
||||||
|
len(schema_result['in_both_database']) > 0:
|
||||||
|
for item in schema_result['in_both_database']:
|
||||||
|
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=item['src_scid'], target_sid=target_sid,
|
||||||
|
target_did=target_did, target_scid=item['tar_scid'],
|
||||||
|
schema_name=item['schema_name'],
|
||||||
|
diff_model_obj=diff_model_obj,
|
||||||
|
total_percent=total_percent,
|
||||||
|
node_percent=node_percent,
|
||||||
|
ignore_whitespaces=ignore_whitespaces)
|
||||||
|
|
||||||
|
comparison_result = \
|
||||||
|
comparison_result + comparison_schema_result
|
||||||
|
|
||||||
|
msg = gettext("Successfully compare the specified databases.")
|
||||||
total_percent = 100
|
total_percent = 100
|
||||||
diff_model_obj.set_comparison_info(msg, total_percent)
|
diff_model_obj.set_comparison_info(msg, total_percent)
|
||||||
# Update the message and total percentage done in session object
|
# Update the message and total percentage done in session object
|
||||||
@@ -609,3 +632,169 @@ def check_version_compatibility(sid, tid):
|
|||||||
|
|
||||||
return False, gettext('Source and Target database server must be of '
|
return False, gettext('Source and Target database server must be of '
|
||||||
'the same major version.')
|
'the same major version.')
|
||||||
|
|
||||||
|
|
||||||
|
def get_schemas(sid, did):
|
||||||
|
"""
|
||||||
|
This function will return the list of schemas for the specified
|
||||||
|
server id and database id.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
view = SchemaDiffRegistry.get_node_view('schema')
|
||||||
|
server = Server.query.filter_by(id=sid).first()
|
||||||
|
response = view.nodes(gid=server.servergroup_id, sid=sid, did=did)
|
||||||
|
schemas = json.loads(response.data)['data']
|
||||||
|
return schemas
|
||||||
|
except Exception as e:
|
||||||
|
app.logger.exception(e)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def compare_database_objects(**kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to compare the specified schema and their children.
|
||||||
|
|
||||||
|
:param kwargs:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
trans_id = kwargs.get('trans_id')
|
||||||
|
session_obj = kwargs.get('session_obj')
|
||||||
|
source_sid = kwargs.get('source_sid')
|
||||||
|
source_did = kwargs.get('source_did')
|
||||||
|
target_sid = kwargs.get('target_sid')
|
||||||
|
target_did = kwargs.get('target_did')
|
||||||
|
diff_model_obj = kwargs.get('diff_model_obj')
|
||||||
|
total_percent = kwargs.get('total_percent')
|
||||||
|
node_percent = kwargs.get('node_percent')
|
||||||
|
ignore_whitespaces = kwargs.get('ignore_whitespaces')
|
||||||
|
comparison_result = []
|
||||||
|
|
||||||
|
all_registered_nodes = SchemaDiffRegistry.get_registered_nodes(None,
|
||||||
|
'Database')
|
||||||
|
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}'). \
|
||||||
|
format(gettext(view.blueprint.collection_label))
|
||||||
|
diff_model_obj.set_comparison_info(msg, total_percent)
|
||||||
|
# Update the message and total percentage in session object
|
||||||
|
update_session_diff_transaction(trans_id, session_obj,
|
||||||
|
diff_model_obj)
|
||||||
|
|
||||||
|
res = view.compare(source_sid=source_sid,
|
||||||
|
source_did=source_did,
|
||||||
|
target_sid=target_sid,
|
||||||
|
target_did=target_did,
|
||||||
|
group_name=gettext('Database Objects'),
|
||||||
|
ignore_whitespaces=ignore_whitespaces)
|
||||||
|
|
||||||
|
if res is not None:
|
||||||
|
comparison_result = comparison_result + res
|
||||||
|
total_percent = total_percent + node_percent
|
||||||
|
|
||||||
|
return comparison_result, total_percent
|
||||||
|
|
||||||
|
|
||||||
|
def compare_schema_objects(**kwargs):
|
||||||
|
"""
|
||||||
|
This function is used to compare the specified schema and their children.
|
||||||
|
|
||||||
|
:param kwargs:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
trans_id = kwargs.get('trans_id')
|
||||||
|
session_obj = kwargs.get('session_obj')
|
||||||
|
source_sid = kwargs.get('source_sid')
|
||||||
|
source_did = kwargs.get('source_did')
|
||||||
|
source_scid = kwargs.get('source_scid')
|
||||||
|
target_sid = kwargs.get('target_sid')
|
||||||
|
target_did = kwargs.get('target_did')
|
||||||
|
target_scid = kwargs.get('target_scid')
|
||||||
|
schema_name = kwargs.get('schema_name')
|
||||||
|
diff_model_obj = kwargs.get('diff_model_obj')
|
||||||
|
total_percent = kwargs.get('total_percent')
|
||||||
|
node_percent = kwargs.get('node_percent')
|
||||||
|
ignore_whitespaces = kwargs.get('ignore_whitespaces')
|
||||||
|
comparison_result = []
|
||||||
|
|
||||||
|
all_registered_nodes = SchemaDiffRegistry.get_registered_nodes()
|
||||||
|
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))
|
||||||
|
diff_model_obj.set_comparison_info(msg, total_percent)
|
||||||
|
# Update the message and total percentage in session object
|
||||||
|
update_session_diff_transaction(trans_id, session_obj,
|
||||||
|
diff_model_obj)
|
||||||
|
|
||||||
|
res = view.compare(source_sid=source_sid,
|
||||||
|
source_did=source_did,
|
||||||
|
source_scid=source_scid,
|
||||||
|
target_sid=target_sid,
|
||||||
|
target_did=target_did,
|
||||||
|
target_scid=target_scid,
|
||||||
|
group_name=gettext(schema_name),
|
||||||
|
ignore_whitespaces=ignore_whitespaces)
|
||||||
|
|
||||||
|
if res is not None:
|
||||||
|
comparison_result = comparison_result + res
|
||||||
|
total_percent = total_percent + node_percent
|
||||||
|
# if total_percent is more then 100 then set it to less then 100
|
||||||
|
if total_percent >= 100:
|
||||||
|
total_percent = 96
|
||||||
|
|
||||||
|
return comparison_result, total_percent
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_compare_schemas(source_sid, source_did, target_sid, target_did):
|
||||||
|
"""
|
||||||
|
This function is used to fetch all the schemas of source and target
|
||||||
|
database and compare them.
|
||||||
|
|
||||||
|
:param source_sid:
|
||||||
|
:param source_did:
|
||||||
|
:param target_sid:
|
||||||
|
:param target_did:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
source_schemas = get_schemas(source_sid, source_did)
|
||||||
|
target_schemas = get_schemas(target_sid, target_did)
|
||||||
|
|
||||||
|
src_schema_dict = {item['label']: item['_id'] for item in source_schemas}
|
||||||
|
tar_schema_dict = {item['label']: item['_id'] for item in target_schemas}
|
||||||
|
|
||||||
|
dict1 = copy.deepcopy(src_schema_dict)
|
||||||
|
dict2 = copy.deepcopy(tar_schema_dict)
|
||||||
|
|
||||||
|
# Find the duplicate keys in both the dictionaries
|
||||||
|
dict1_keys = set(dict1.keys())
|
||||||
|
dict2_keys = set(dict2.keys())
|
||||||
|
intersect_keys = dict1_keys.intersection(dict2_keys)
|
||||||
|
|
||||||
|
# Keys that are available in source and missing in target.
|
||||||
|
source_only = []
|
||||||
|
added = dict1_keys - dict2_keys
|
||||||
|
for item in added:
|
||||||
|
source_only.append({'schema_name': item,
|
||||||
|
'scid': src_schema_dict[item]})
|
||||||
|
|
||||||
|
target_only = []
|
||||||
|
# Keys that are available in target and missing in source.
|
||||||
|
removed = dict2_keys - dict1_keys
|
||||||
|
for item in removed:
|
||||||
|
target_only.append({'schema_name': item,
|
||||||
|
'scid': tar_schema_dict[item]})
|
||||||
|
|
||||||
|
in_both_database = []
|
||||||
|
for item in intersect_keys:
|
||||||
|
in_both_database.append({'schema_name': item,
|
||||||
|
'src_scid': src_schema_dict[item],
|
||||||
|
'tar_scid': tar_schema_dict[item]})
|
||||||
|
|
||||||
|
schema_result = {'source_only': source_only, 'target_only': target_only,
|
||||||
|
'in_both_database': in_both_database}
|
||||||
|
|
||||||
|
return schema_result
|
||||||
|
|||||||
@@ -9,20 +9,17 @@
|
|||||||
|
|
||||||
"""Schema diff object comparison."""
|
"""Schema diff object comparison."""
|
||||||
|
|
||||||
import copy
|
|
||||||
|
|
||||||
from flask import render_template
|
from flask import render_template
|
||||||
from flask_babelex import gettext
|
from flask_babelex import gettext
|
||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
from pgadmin.utils.ajax import internal_server_error
|
from pgadmin.utils.ajax import internal_server_error
|
||||||
from pgadmin.tools.schema_diff.directory_compare import compare_dictionaries
|
from pgadmin.tools.schema_diff.directory_compare import compare_dictionaries
|
||||||
from pgadmin.tools.schema_diff.model import SchemaDiffModel
|
|
||||||
|
|
||||||
|
|
||||||
class SchemaDiffObjectCompare:
|
class SchemaDiffObjectCompare:
|
||||||
|
|
||||||
keys_to_ignore = ['oid', 'schema']
|
keys_to_ignore = ['oid', 'oid-2']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_schema(sid, did, scid):
|
def get_schema(sid, did, scid):
|
||||||
@@ -57,27 +54,27 @@ class SchemaDiffObjectCompare:
|
|||||||
:param kwargs:
|
:param kwargs:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
source_params = {'sid': kwargs.get('source_sid'),
|
source_params = {'sid': kwargs.get('source_sid'),
|
||||||
'did': kwargs.get('source_did'),
|
'did': kwargs.get('source_did')}
|
||||||
'scid': kwargs.get('source_scid')
|
|
||||||
}
|
|
||||||
|
|
||||||
target_params = {'sid': kwargs.get('target_sid'),
|
target_params = {'sid': kwargs.get('target_sid'),
|
||||||
'did': kwargs.get('target_did'),
|
'did': kwargs.get('target_did')}
|
||||||
'scid': kwargs.get('target_scid')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
group_name = kwargs.get('group_name')
|
||||||
ignore_whitespaces = kwargs.get('ignore_whitespaces')
|
ignore_whitespaces = kwargs.get('ignore_whitespaces')
|
||||||
status, target_schema = self.get_schema(kwargs.get('target_sid'),
|
source = {}
|
||||||
kwargs.get('target_did'),
|
target = {}
|
||||||
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)
|
||||||
|
else:
|
||||||
|
source_params['scid'] = kwargs.get('source_scid')
|
||||||
|
target_params['scid'] = kwargs.get('target_scid')
|
||||||
|
|
||||||
|
if 'scid' in source_params and source_params['scid'] is not None:
|
||||||
source = self.fetch_objects_to_compare(**source_params)
|
source = self.fetch_objects_to_compare(**source_params)
|
||||||
|
|
||||||
|
if 'scid' in target_params and target_params['scid'] is not None:
|
||||||
target = self.fetch_objects_to_compare(**target_params)
|
target = self.fetch_objects_to_compare(**target_params)
|
||||||
|
|
||||||
# If both the dict have no items then return None.
|
# If both the dict have no items then return None.
|
||||||
@@ -88,11 +85,11 @@ class SchemaDiffObjectCompare:
|
|||||||
return compare_dictionaries(view_object=self,
|
return compare_dictionaries(view_object=self,
|
||||||
source_params=source_params,
|
source_params=source_params,
|
||||||
target_params=target_params,
|
target_params=target_params,
|
||||||
target_schema=target_schema,
|
|
||||||
source_dict=source,
|
source_dict=source,
|
||||||
target_dict=target,
|
target_dict=target,
|
||||||
node=self.node_type,
|
node=self.node_type,
|
||||||
node_label=self.blueprint.collection_label,
|
node_label=self.blueprint.collection_label,
|
||||||
|
group_name=group_name,
|
||||||
ignore_whitespaces=ignore_whitespaces,
|
ignore_whitespaces=ignore_whitespaces,
|
||||||
ignore_keys=self.keys_to_ignore)
|
ignore_keys=self.keys_to_ignore)
|
||||||
|
|
||||||
@@ -105,17 +102,23 @@ class SchemaDiffObjectCompare:
|
|||||||
source_params = {'gid': 1,
|
source_params = {'gid': 1,
|
||||||
'sid': kwargs.get('source_sid'),
|
'sid': kwargs.get('source_sid'),
|
||||||
'did': kwargs.get('source_did'),
|
'did': kwargs.get('source_did'),
|
||||||
'scid': kwargs.get('source_scid'),
|
|
||||||
'oid': kwargs.get('source_oid')
|
'oid': kwargs.get('source_oid')
|
||||||
}
|
}
|
||||||
|
|
||||||
target_params = {'gid': 1,
|
target_params = {'gid': 1,
|
||||||
'sid': kwargs.get('target_sid'),
|
'sid': kwargs.get('target_sid'),
|
||||||
'did': kwargs.get('target_did'),
|
'did': kwargs.get('target_did'),
|
||||||
'scid': kwargs.get('target_scid'),
|
|
||||||
'oid': kwargs.get('target_oid')
|
'oid': kwargs.get('target_oid')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
source_scid = kwargs.get('source_scid')
|
||||||
|
if source_scid is not None and source_scid != 0:
|
||||||
|
source_params['scid'] = source_scid
|
||||||
|
|
||||||
|
target_scid = kwargs.get('target_scid')
|
||||||
|
if target_scid is not None and target_scid != 0:
|
||||||
|
target_params['scid'] = target_scid
|
||||||
|
|
||||||
source = self.get_sql_from_diff(**source_params)
|
source = self.get_sql_from_diff(**source_params)
|
||||||
target = self.get_sql_from_diff(**target_params)
|
target = self.get_sql_from_diff(**target_params)
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ from pgadmin.tools.schema_diff.model import SchemaDiffModel
|
|||||||
count = 1
|
count = 1
|
||||||
|
|
||||||
list_keys_array = ['name', 'colname', 'argid', 'token', 'option', 'conname',
|
list_keys_array = ['name', 'colname', 'argid', 'token', 'option', 'conname',
|
||||||
'member_name', 'label', 'attname']
|
'member_name', 'label', 'attname', 'fdwoption',
|
||||||
|
'fsrvoption', 'umoption']
|
||||||
|
|
||||||
|
|
||||||
def compare_dictionaries(**kwargs):
|
def compare_dictionaries(**kwargs):
|
||||||
@@ -29,7 +30,7 @@ def compare_dictionaries(**kwargs):
|
|||||||
view_object = kwargs.get('view_object')
|
view_object = kwargs.get('view_object')
|
||||||
source_params = kwargs.get('source_params')
|
source_params = kwargs.get('source_params')
|
||||||
target_params = kwargs.get('target_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')
|
source_dict = kwargs.get('source_dict')
|
||||||
target_dict = kwargs.get('target_dict')
|
target_dict = kwargs.get('target_dict')
|
||||||
node = kwargs.get('node')
|
node = kwargs.get('node')
|
||||||
@@ -50,6 +51,7 @@ def compare_dictionaries(**kwargs):
|
|||||||
|
|
||||||
# Keys that are available in source and missing in target.
|
# Keys that are available in source and missing in target.
|
||||||
source_only = []
|
source_only = []
|
||||||
|
source_dependencies = []
|
||||||
added = dict1_keys - dict2_keys
|
added = dict1_keys - dict2_keys
|
||||||
global count
|
global count
|
||||||
for item in added:
|
for item in added:
|
||||||
@@ -63,18 +65,25 @@ def compare_dictionaries(**kwargs):
|
|||||||
temp_src_params['json_resp'] = False
|
temp_src_params['json_resp'] = False
|
||||||
source_ddl = \
|
source_ddl = \
|
||||||
view_object.get_sql_from_table_diff(**temp_src_params)
|
view_object.get_sql_from_table_diff(**temp_src_params)
|
||||||
temp_src_params.update({
|
|
||||||
'diff_schema': target_schema
|
|
||||||
})
|
|
||||||
diff_ddl = view_object.get_sql_from_table_diff(**temp_src_params)
|
diff_ddl = view_object.get_sql_from_table_diff(**temp_src_params)
|
||||||
|
source_dependencies = \
|
||||||
|
view_object.get_table_submodules_dependencies(
|
||||||
|
**temp_src_params)
|
||||||
else:
|
else:
|
||||||
temp_src_params = copy.deepcopy(source_params)
|
temp_src_params = copy.deepcopy(source_params)
|
||||||
temp_src_params['oid'] = source_object_id
|
temp_src_params['oid'] = source_object_id
|
||||||
|
# Provide Foreign Data Wrapper ID
|
||||||
|
if 'fdwid' in source_dict[item]:
|
||||||
|
temp_src_params['fdwid'] = source_dict[item]['fdwid']
|
||||||
|
# Provide Foreign Server ID
|
||||||
|
if 'fsid' in source_dict[item]:
|
||||||
|
temp_src_params['fsid'] = source_dict[item]['fsid']
|
||||||
|
|
||||||
source_ddl = view_object.get_sql_from_diff(**temp_src_params)
|
source_ddl = view_object.get_sql_from_diff(**temp_src_params)
|
||||||
temp_src_params.update({
|
|
||||||
'diff_schema': target_schema
|
|
||||||
})
|
|
||||||
diff_ddl = view_object.get_sql_from_diff(**temp_src_params)
|
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,
|
||||||
|
show_system_objects=None, is_schema_diff=True)
|
||||||
|
|
||||||
source_only.append({
|
source_only.append({
|
||||||
'id': count,
|
'id': count,
|
||||||
@@ -85,7 +94,9 @@ def compare_dictionaries(**kwargs):
|
|||||||
'status': SchemaDiffModel.COMPARISON_STATUS['source_only'],
|
'status': SchemaDiffModel.COMPARISON_STATUS['source_only'],
|
||||||
'source_ddl': source_ddl,
|
'source_ddl': source_ddl,
|
||||||
'target_ddl': '',
|
'target_ddl': '',
|
||||||
'diff_ddl': diff_ddl
|
'diff_ddl': diff_ddl,
|
||||||
|
'group_name': group_name,
|
||||||
|
'dependencies': source_dependencies
|
||||||
})
|
})
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
@@ -110,6 +121,13 @@ def compare_dictionaries(**kwargs):
|
|||||||
else:
|
else:
|
||||||
temp_tgt_params = copy.deepcopy(target_params)
|
temp_tgt_params = copy.deepcopy(target_params)
|
||||||
temp_tgt_params['oid'] = target_object_id
|
temp_tgt_params['oid'] = target_object_id
|
||||||
|
# Provide Foreign Data Wrapper ID
|
||||||
|
if 'fdwid' in target_dict[item]:
|
||||||
|
temp_tgt_params['fdwid'] = target_dict[item]['fdwid']
|
||||||
|
# Provide Foreign Server ID
|
||||||
|
if 'fsid' in target_dict[item]:
|
||||||
|
temp_tgt_params['fsid'] = target_dict[item]['fsid']
|
||||||
|
|
||||||
target_ddl = view_object.get_sql_from_diff(**temp_tgt_params)
|
target_ddl = view_object.get_sql_from_diff(**temp_tgt_params)
|
||||||
temp_tgt_params.update(
|
temp_tgt_params.update(
|
||||||
{'drop_sql': True})
|
{'drop_sql': True})
|
||||||
@@ -124,13 +142,16 @@ def compare_dictionaries(**kwargs):
|
|||||||
'status': SchemaDiffModel.COMPARISON_STATUS['target_only'],
|
'status': SchemaDiffModel.COMPARISON_STATUS['target_only'],
|
||||||
'source_ddl': '',
|
'source_ddl': '',
|
||||||
'target_ddl': target_ddl,
|
'target_ddl': target_ddl,
|
||||||
'diff_ddl': diff_ddl
|
'diff_ddl': diff_ddl,
|
||||||
|
'group_name': group_name,
|
||||||
|
'dependencies': []
|
||||||
})
|
})
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
# Compare the values of duplicates keys.
|
# Compare the values of duplicates keys.
|
||||||
identical = []
|
identical = []
|
||||||
different = []
|
different = []
|
||||||
|
diff_dependencies = []
|
||||||
for key in intersect_keys:
|
for key in intersect_keys:
|
||||||
source_object_id = None
|
source_object_id = None
|
||||||
target_object_id = None
|
target_object_id = None
|
||||||
@@ -149,7 +170,13 @@ def compare_dictionaries(**kwargs):
|
|||||||
'oid': source_object_id,
|
'oid': source_object_id,
|
||||||
'source_oid': source_object_id,
|
'source_oid': source_object_id,
|
||||||
'target_oid': target_object_id,
|
'target_oid': target_object_id,
|
||||||
'status': SchemaDiffModel.COMPARISON_STATUS['identical']
|
'status': SchemaDiffModel.COMPARISON_STATUS['identical'],
|
||||||
|
'group_name': group_name,
|
||||||
|
'dependencies': [],
|
||||||
|
'source_scid': source_params['scid']
|
||||||
|
if 'scid' in source_params else 0,
|
||||||
|
'target_scid': target_params['scid']
|
||||||
|
if 'scid' in target_params else 0,
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
if node == 'table':
|
if node == 'table':
|
||||||
@@ -174,12 +201,14 @@ def compare_dictionaries(**kwargs):
|
|||||||
|
|
||||||
source_ddl = \
|
source_ddl = \
|
||||||
view_object.get_sql_from_table_diff(**temp_src_params)
|
view_object.get_sql_from_table_diff(**temp_src_params)
|
||||||
|
diff_dependencies = \
|
||||||
|
view_object.get_table_submodules_dependencies(
|
||||||
|
**temp_src_params)
|
||||||
target_ddl = \
|
target_ddl = \
|
||||||
view_object.get_sql_from_table_diff(**temp_tgt_params)
|
view_object.get_sql_from_table_diff(**temp_tgt_params)
|
||||||
diff_ddl = view_object.get_sql_from_submodule_diff(
|
diff_ddl = view_object.get_sql_from_submodule_diff(
|
||||||
source_params=temp_src_params,
|
source_params=temp_src_params,
|
||||||
target_params=temp_tgt_params,
|
target_params=temp_tgt_params,
|
||||||
target_schema=target_schema,
|
|
||||||
source=dict1[key], target=dict2[key], diff_dict=diff_dict,
|
source=dict1[key], target=dict2[key], diff_dict=diff_dict,
|
||||||
ignore_whitespaces=ignore_whitespaces)
|
ignore_whitespaces=ignore_whitespaces)
|
||||||
else:
|
else:
|
||||||
@@ -193,7 +222,19 @@ def compare_dictionaries(**kwargs):
|
|||||||
|
|
||||||
temp_src_params['oid'] = source_object_id
|
temp_src_params['oid'] = source_object_id
|
||||||
temp_tgt_params['oid'] = target_object_id
|
temp_tgt_params['oid'] = target_object_id
|
||||||
|
# Provide Foreign Data Wrapper ID
|
||||||
|
if 'fdwid' in source_dict[key]:
|
||||||
|
temp_src_params['fdwid'] = source_dict[key]['fdwid']
|
||||||
|
temp_tgt_params['fdwid'] = target_dict[key]['fdwid']
|
||||||
|
# Provide Foreign Server ID
|
||||||
|
if 'fsid' in source_dict[key]:
|
||||||
|
temp_src_params['fsid'] = source_dict[key]['fsid']
|
||||||
|
temp_tgt_params['fsid'] = target_dict[key]['fsid']
|
||||||
|
|
||||||
source_ddl = view_object.get_sql_from_diff(**temp_src_params)
|
source_ddl = view_object.get_sql_from_diff(**temp_src_params)
|
||||||
|
diff_dependencies = view_object.get_dependencies(
|
||||||
|
view_object.conn, source_object_id, where=None,
|
||||||
|
show_system_objects=None, is_schema_diff=True)
|
||||||
target_ddl = view_object.get_sql_from_diff(**temp_tgt_params)
|
target_ddl = view_object.get_sql_from_diff(**temp_tgt_params)
|
||||||
temp_tgt_params.update(
|
temp_tgt_params.update(
|
||||||
{'data': diff_dict})
|
{'data': diff_dict})
|
||||||
@@ -210,7 +251,9 @@ def compare_dictionaries(**kwargs):
|
|||||||
'status': SchemaDiffModel.COMPARISON_STATUS['different'],
|
'status': SchemaDiffModel.COMPARISON_STATUS['different'],
|
||||||
'source_ddl': source_ddl,
|
'source_ddl': source_ddl,
|
||||||
'target_ddl': target_ddl,
|
'target_ddl': target_ddl,
|
||||||
'diff_ddl': diff_ddl
|
'diff_ddl': diff_ddl,
|
||||||
|
'group_name': group_name,
|
||||||
|
'dependencies': diff_dependencies
|
||||||
})
|
})
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
@@ -498,13 +541,13 @@ def sort_list(source, target):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
# Check the above keys are exist in the dictionary
|
# Check the above keys are exist in the dictionary
|
||||||
if len(source) > 0 and type(source[0]) == dict:
|
if source is not None and len(source) > 0 and type(source[0]) == dict:
|
||||||
tmp_key = is_key_exists(list_keys_array, source[0])
|
tmp_key = is_key_exists(list_keys_array, source[0])
|
||||||
if tmp_key is not None:
|
if tmp_key is not None:
|
||||||
source = sorted(source, key=lambda k: k[tmp_key])
|
source = sorted(source, key=lambda k: k[tmp_key])
|
||||||
|
|
||||||
# Check the above keys are exist in the dictionary
|
# Check the above keys are exist in the dictionary
|
||||||
if len(target) > 0 and type(target[0]) == dict:
|
if target is not None and len(target) > 0 and type(target[0]) == dict:
|
||||||
tmp_key = is_key_exists(list_keys_array, target[0])
|
tmp_key = is_key_exists(list_keys_array, target[0])
|
||||||
if tmp_key is not None:
|
if tmp_key is not None:
|
||||||
target = sorted(target, key=lambda k: k[tmp_key])
|
target = sorted(target, key=lambda k: k[tmp_key])
|
||||||
|
|||||||
@@ -162,3 +162,7 @@
|
|||||||
.slick-cell .ml-2 {
|
.slick-cell .ml-2 {
|
||||||
margin-left: 2rem !important;
|
margin-left: 2rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slick-cell .ml-3 {
|
||||||
|
margin-left: 3rem !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ let SchemaDiffSelect2Control =
|
|||||||
controlsClassName: 'pgadmin-controls pg-el-sm-11 pg-el-12',
|
controlsClassName: 'pgadmin-controls pg-el-sm-11 pg-el-12',
|
||||||
}),
|
}),
|
||||||
className: function() {
|
className: function() {
|
||||||
return 'pgadmin-controls pg-el-sm-4';
|
return 'pgadmin-controls pg-el-sm-6';
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
'focus select': 'clearInvalid',
|
'focus select': 'clearInvalid',
|
||||||
|
|||||||
@@ -39,10 +39,8 @@ export default class SchemaDiffUI {
|
|||||||
this.model = new Backbone.Model({
|
this.model = new Backbone.Model({
|
||||||
source_sid: undefined,
|
source_sid: undefined,
|
||||||
source_did: undefined,
|
source_did: undefined,
|
||||||
source_scid: undefined,
|
|
||||||
target_sid: undefined,
|
target_sid: undefined,
|
||||||
target_did: undefined,
|
target_did: undefined,
|
||||||
target_scid: undefined,
|
|
||||||
source_ddl: undefined,
|
source_ddl: undefined,
|
||||||
target_ddl: undefined,
|
target_ddl: undefined,
|
||||||
diff_ddl: undefined,
|
diff_ddl: undefined,
|
||||||
@@ -109,7 +107,6 @@ export default class SchemaDiffUI {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
raise_error_on_fail(alert_title, xhr) {
|
raise_error_on_fail(alert_title, xhr) {
|
||||||
try {
|
try {
|
||||||
var err = JSON.parse(xhr.responseText);
|
var err = JSON.parse(xhr.responseText);
|
||||||
@@ -147,10 +144,8 @@ export default class SchemaDiffUI {
|
|||||||
|
|
||||||
if (url_params['source_sid'] == '' || _.isUndefined(url_params['source_sid']) ||
|
if (url_params['source_sid'] == '' || _.isUndefined(url_params['source_sid']) ||
|
||||||
url_params['source_did'] == '' || _.isUndefined(url_params['source_did']) ||
|
url_params['source_did'] == '' || _.isUndefined(url_params['source_did']) ||
|
||||||
url_params['source_scid'] == '' || _.isUndefined(url_params['source_scid']) ||
|
|
||||||
url_params['target_sid'] == '' || _.isUndefined(url_params['target_sid']) ||
|
url_params['target_sid'] == '' || _.isUndefined(url_params['target_sid']) ||
|
||||||
url_params['target_did'] == '' || _.isUndefined(url_params['target_did']) ||
|
url_params['target_did'] == '' || _.isUndefined(url_params['target_did'])
|
||||||
url_params['target_scid'] == '' || _.isUndefined(url_params['target_scid'])
|
|
||||||
) {
|
) {
|
||||||
Alertify.alert(gettext('Selection Error'), gettext('Please select source and target.'));
|
Alertify.alert(gettext('Selection Error'), gettext('Please select source and target.'));
|
||||||
return false;
|
return false;
|
||||||
@@ -289,18 +284,18 @@ export default class SchemaDiffUI {
|
|||||||
// Format Schema object title with appropriate icon
|
// Format Schema object title with appropriate icon
|
||||||
var formatColumnTitle = function (row, cell, value, columnDef, dataContext) {
|
var formatColumnTitle = function (row, cell, value, columnDef, dataContext) {
|
||||||
let icon = 'icon-' + dataContext.type;
|
let icon = 'icon-' + dataContext.type;
|
||||||
return '<i class="ml-2 wcTabIcon '+ icon +'"></i><span>' + value + '</span>';
|
return '<i class="ml-3 wcTabIcon '+ icon +'"></i><span>' + value + '</span>';
|
||||||
};
|
};
|
||||||
|
|
||||||
// Grid Columns
|
// Grid Columns
|
||||||
var grid_width = (self.grid_width - 47) / 2 ;
|
var grid_width = (self.grid_width - 47) / 2 ;
|
||||||
var columns = [
|
var columns = [
|
||||||
checkboxSelector.getColumnDefinition(),
|
checkboxSelector.getColumnDefinition(),
|
||||||
{id: 'title', name: gettext('Schema Objects'), field: 'title', minWidth: grid_width, formatter: formatColumnTitle},
|
{id: 'title', name: gettext('Objects'), field: 'title', minWidth: grid_width, formatter: formatColumnTitle},
|
||||||
{id: 'status', name: gettext('Comparison Result'), field: 'status', minWidth: grid_width},
|
{id: 'status', name: gettext('Comparison Result'), field: 'status', minWidth: grid_width},
|
||||||
{id: 'label', name: gettext('Schema Objects'), field: 'label', width: 0, minWidth: 0, maxWidth: 0,
|
{id: 'label', name: gettext('Objects'), field: 'label', width: 0, minWidth: 0, maxWidth: 0,
|
||||||
cssClass: 'really-hidden', headerCssClass: 'really-hidden'},
|
cssClass: 'really-hidden', headerCssClass: 'really-hidden'},
|
||||||
{id: 'type', name: gettext('Schema Objects'), field: 'type', width: 0, minWidth: 0, maxWidth: 0,
|
{id: 'type', name: gettext('Objects'), field: 'type', width: 0, minWidth: 0, maxWidth: 0,
|
||||||
cssClass: 'really-hidden', headerCssClass: 'really-hidden'},
|
cssClass: 'really-hidden', headerCssClass: 'really-hidden'},
|
||||||
{id: 'id', name: 'id', field: 'id', width: 0, minWidth: 0, maxWidth: 0,
|
{id: 'id', name: 'id', field: 'id', width: 0, minWidth: 0, maxWidth: 0,
|
||||||
cssClass: 'really-hidden', headerCssClass: 'really-hidden' },
|
cssClass: 'really-hidden', headerCssClass: 'really-hidden' },
|
||||||
@@ -316,7 +311,18 @@ export default class SchemaDiffUI {
|
|||||||
|
|
||||||
// Grouping by Schema Object
|
// Grouping by Schema Object
|
||||||
self.groupBySchemaObject = function() {
|
self.groupBySchemaObject = function() {
|
||||||
self.dataView.setGrouping({
|
self.dataView.setGrouping([{
|
||||||
|
getter: 'group_name',
|
||||||
|
formatter: function (g) {
|
||||||
|
let icon = 'icon-schema';
|
||||||
|
if (g.rows[0].group_name == 'Database Objects'){
|
||||||
|
icon = 'icon-coll-database';
|
||||||
|
}
|
||||||
|
return '<i class="wcTabIcon '+ icon +'"></i><span>' + g.rows[0].group_name;
|
||||||
|
},
|
||||||
|
aggregateCollapsed: true,
|
||||||
|
lazyTotalsCalculation: true,
|
||||||
|
}, {
|
||||||
getter: 'type',
|
getter: 'type',
|
||||||
formatter: function (g) {
|
formatter: function (g) {
|
||||||
let icon = 'icon-coll-' + g.value;
|
let icon = 'icon-coll-' + g.value;
|
||||||
@@ -330,8 +336,9 @@ export default class SchemaDiffUI {
|
|||||||
return '<i class="wcTabIcon '+ icon +'"></i><span>' + g.rows[0].label + ' - ' + gettext('Identical') + ': <strong>' + identical + '</strong> ' + gettext('Different') + ': <strong>' + different + '</strong> ' + gettext('Source Only') + ': <strong>' + source_only + '</strong> ' + gettext('Target Only') + ': <strong>' + target_only + '</strong></span>';
|
return '<i class="wcTabIcon '+ icon +'"></i><span>' + g.rows[0].label + ' - ' + gettext('Identical') + ': <strong>' + identical + '</strong> ' + gettext('Different') + ': <strong>' + different + '</strong> ' + gettext('Source Only') + ': <strong>' + source_only + '</strong> ' + gettext('Target Only') + ': <strong>' + target_only + '</strong></span>';
|
||||||
},
|
},
|
||||||
aggregateCollapsed: true,
|
aggregateCollapsed: true,
|
||||||
|
collapsed: true,
|
||||||
lazyTotalsCalculation: true,
|
lazyTotalsCalculation: true,
|
||||||
});
|
}]);
|
||||||
};
|
};
|
||||||
|
|
||||||
var groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider({ checkboxSelect: true,
|
var groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider({ checkboxSelect: true,
|
||||||
@@ -503,6 +510,8 @@ export default class SchemaDiffUI {
|
|||||||
target_oid = data.target_oid;
|
target_oid = data.target_oid;
|
||||||
|
|
||||||
url_params['trans_id'] = self.trans_id;
|
url_params['trans_id'] = self.trans_id;
|
||||||
|
url_params['source_scid'] = data.source_scid;
|
||||||
|
url_params['target_scid'] = data.target_scid;
|
||||||
url_params['source_oid'] = source_oid;
|
url_params['source_oid'] = source_oid;
|
||||||
url_params['target_oid'] = target_oid;
|
url_params['target_oid'] = target_oid;
|
||||||
url_params['comp_status'] = data.status;
|
url_params['comp_status'] = data.status;
|
||||||
@@ -607,37 +616,6 @@ export default class SchemaDiffUI {
|
|||||||
connect: function() {
|
connect: function() {
|
||||||
self.connect_database(this.model.get('source_sid'), arguments[0], arguments[1]);
|
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) {
|
|
||||||
let self_local = this;
|
|
||||||
if (!_.isUndefined(m.get('source_did')) && !_.isNull(m.get('source_did'))
|
|
||||||
&& m.get('source_did') !== '') {
|
|
||||||
setTimeout(function() {
|
|
||||||
if (self_local.options.length > 0) {
|
|
||||||
m.set('source_scid', self_local.options[0].value);
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
m.set('source_scid', undefined);
|
|
||||||
}, 10);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
}, {
|
}, {
|
||||||
name: 'target_sid', label: false,
|
name: 'target_sid', label: false,
|
||||||
control: SchemaDiffSelect2Control,
|
control: SchemaDiffSelect2Control,
|
||||||
@@ -698,37 +676,6 @@ export default class SchemaDiffUI {
|
|||||||
connect: function() {
|
connect: function() {
|
||||||
self.connect_database(this.model.get('target_sid'), arguments[0], arguments[1]);
|
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) {
|
|
||||||
let self_local = this;
|
|
||||||
if (!_.isUndefined(m.get('target_did')) && !_.isNull(m.get('target_did'))
|
|
||||||
&& m.get('target_did') !== '') {
|
|
||||||
setTimeout(function() {
|
|
||||||
if (self_local.options.length > 0) {
|
|
||||||
m.set('target_scid', self_local.options[0].value);
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
m.set('target_scid', undefined);
|
|
||||||
}, 10);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -760,7 +707,7 @@ export default class SchemaDiffUI {
|
|||||||
|
|
||||||
footer_panel.$container.find('#schema-diff-ddl-comp').append(self.footer.render().$el);
|
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'>
|
header_panel.$container.find('#schema-diff-grid').append(`<div class='obj_properties container-fluid'>
|
||||||
<div class='pg-panel-message'>` + gettext('Select the server, database and schema for the source and target and click <strong>Compare</strong> to compare them.') + '</div></div>');
|
<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>');
|
||||||
|
|
||||||
self.grid_width = $('#schema-diff-grid').width();
|
self.grid_width = $('#schema-diff-grid').width();
|
||||||
self.grid_height = this.panel_obj.height();
|
self.grid_height = this.panel_obj.height();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from pgadmin.utils.versioned_template_loader import \
|
|||||||
get_version_mapping_directories
|
get_version_mapping_directories
|
||||||
|
|
||||||
|
|
||||||
class SchemaDiffTestCase(BaseTestGenerator):
|
class SchemaDiffTestCase():
|
||||||
""" This class will test the schema diff. """
|
""" This class will test the schema diff. """
|
||||||
scenarios = [
|
scenarios = [
|
||||||
# Fetching default URL for database node.
|
# Fetching default URL for database node.
|
||||||
|
|||||||